Тесты на состояние гонки в эликсире - PullRequest
0 голосов
/ 26 января 2020

Я пытаюсь написать тесты для случая, когда мне нужно протестировать метод с from(...) |> lock("FOR UPDATE") и убедиться, что строка будет заблокирована от других процессов. Я пытался написать этот тест:

defmodule Chain.BalanceTest do
  use Chain.DataCase

  describe "concurrent" do
    setup do
      {:ok, %Chain.Address{id: id}} = Chain.Address.create_address(%{user_id: 1, nonce: 0})

      :ok
    end

    test "test locking" do
      parent = self()
      %Chain.Address{id: id} = from(a in Chain.Address) |> Repo.one()

      {:ok, new_pid} =
        Task.start_link(fn ->
          assert_receive :wait, 5000

          Repo.transaction(fn ->
            address = Chain.Address.lock_address(id)
            Apex.ap("1 - #{address.nonce}")
            Chain.Address.update_nonce(address)
          end)

          send(parent, :done)
        end)

      Repo.transaction(fn ->
        address = Chain.Address.lock_address(id)
        Apex.ap("2 - #{address.nonce}")
        send(new_pid, :wait)
        Chain.Address.update_nonce(address)
      end)

      assert_receive :done, 5000

      fetched = Chain.Address.get!(id)
      assert fetched.nonce == 2
    end
  end
end

Проблема в том, что он работает на уровне изоляции транзакций и всегда работает, даже если я удаляю lock из Chain.Addres.lock_address. Я попытался Sandbox.checkout в Task, но в этом случае Task процесс не видит этот адрес, потому что родительский процесс не зафиксировал его.

Так есть ли способ вызвать состояние гонки во время теста и \ или сохранить данные идиоматическим способом c, чтобы другой процесс мог прочитать их и не испортил все другие тесты?

1 Ответ

1 голос
/ 07 февраля 2020

Нет способа обнаружить взаимоблокировки в общем случае. Вы можете использовать TLA + для моделирования вашего приложения и проверки этой модели на наличие ошибок.

В качестве альтернативы вы можете проверить Concuerror , чтобы попытаться создать взаимоблокировки в тестовом наборе, однако это не гарантирует, что в вашей модели нет тупиков

...