packages feed

polysemy-conc-0.10.0.0: test/Polysemy/Conc/Test/LockTest.hs

{-# options_ghc -fplugin=Polysemy.Plugin #-}

module Polysemy.Conc.Test.LockTest where

import Polysemy.Test (UnitTest, assert, assertJust, runTestAuto, unitTest)
import Polysemy.Time (GhcTime, MilliSeconds (MilliSeconds), Seconds (Seconds), interpretTimeGhc)
import Test.Tasty (TestTree, testGroup)

import qualified Polysemy.Conc.Effect.Lock as Lock
import Polysemy.Conc.Effect.Lock (Lock)
import Polysemy.Conc.Effect.Mask (Mask)
import Polysemy.Conc.Effect.Race (Race)
import qualified Polysemy.Conc.Effect.Sync as Sync
import Polysemy.Conc.Interpreter.Lock (interpretLockReentrant)
import Polysemy.Conc.Interpreter.Mask (interpretMaskFinal)
import Polysemy.Conc.Interpreter.Race (interpretRace)
import Polysemy.Conc.Interpreter.Sync (interpretSync)
import Polysemy.Conc.Race (timeout_)

interpretLockTest ::
  Members [Resource, Embed IO, Final IO] r =>
  InterpretersFor [Lock, Mask, Race, Async, GhcTime] r
interpretLockTest =
  interpretTimeGhc .
  asyncToIOFinal .
  interpretRace .
  interpretMaskFinal .
  interpretLockReentrant

test_lockBasic :: UnitTest
test_lockBasic =
  runTestAuto $ interpretLockTest $ interpretSync @(Proxy 1) $ interpretSync @(Proxy 2) do
    t1 <- async do
      Lock.lock do
        assert =<< Sync.putTry (Proxy @1)
        assertJust Proxy =<< Sync.wait @(Proxy 2) (Seconds 5)
    assertJust Proxy =<< Sync.wait @(Proxy 1) (Seconds 5)
    assert =<< Lock.lockOr (pure True) (pure False)
    assert =<< timeout_ (pure True) (MilliSeconds 50) (Lock.lock (pure False))
    assert =<< Sync.putTry (Proxy @2)
    assertJust () =<< await t1

test_lockReentry :: UnitTest
test_lockReentry =
  runTestAuto $ interpretLockTest do
    Lock.lock do
      assert =<< Lock.lockOr (pure False) (pure True)
      assertJust True =<< await =<< async do
        assert =<< timeout_ (pure True) (MilliSeconds 50) (Lock.lock (pure False))
        Lock.lockOr (pure True) (pure False)

test_lock :: TestTree
test_lock =
  testGroup "lock" [
    unitTest "basic" test_lockBasic,
    unitTest "reentry" test_lockReentry
  ]