content: {-
    Copyright (c) Meta Platforms, Inc. and affiliates.
    All rights reserved.
  
    This source code is licensed under the BSD-style license found in the
    LICENSE file in the root directory of this source tree.
  -}
  
  module RWVarTest (main) where
  
  import Test.HUnit
  import TestRunner
  
  import Facebook.Init
  import Util.RWVar
  import Util.HUnit
  
  readTest :: Test
  readTest = TestLabel "readTest" $ TestCase $ do
    var <- newRWVar expected
    withReadRWVar var $ \v ->
      assertEqual "got expected back" expected v
    where
      expected = 'a'
  
  writeTest :: Test
  writeTest = TestLabel "writeTest" $ TestCase $ do
    var <- newRWVar initial
    withWriteRWVar var $ \v -> do
      assertEqual "got initial" initial v
      return (update, ())
    withReadRWVar var $ \v ->
      assertEqual "got updated value" update v
    where
      initial :: Int
      initial = 42
      update = 1337
  
  readReadTest :: Test
  readReadTest = TestLabel "nestedReads" $ TestCase $ do
    var <- newRWVar val
    withReadRWVar var $ \x -> do
      assertEqual "first got value" val x
      withReadRWVar var $ \y ->
        assertEqual "second got value" val y
    where
      val = 'a'
  
  readWriteDeadlockTest :: Test
  readWriteDeadlockTest = TestLabel "read then write deadlocks" $ TestCase $ do
    var <- newRWVar 'a'
    assertThrow "deadlocks" $
      withReadRWVar var $ \_ ->
        withWriteRWVar var $ \a -> return (a, ())
  
  writeReadDeadlockTest :: Test
  writeReadDeadlockTest = TestLabel "write then read deadlocks" $ TestCase $ do
    var <- newRWVar 'a'
    assertThrow "deadlocks" $
      withWriteRWVar var $ \a -> do
        _ <- withReadRWVar var return
        return (a, ())
  
  writeWriteDeadlockTest :: Test
  writeWriteDeadlockTest = TestLabel "write then write deadlocks" $ TestCase $ do
    var <- newRWVar 'a'
    assertThrow "deadlocks" $
      withWriteRWVar var $ \x -> do
        _ <- withWriteRWVar var $ \y -> return (y, ())
        return (x, ())
  
  
  main :: IO ()
  main = withFacebookUnitTest $
    testRunner $ TestList
     [ readTest
     , writeTest
     , readReadTest
     , readWriteDeadlockTest
     , writeReadDeadlockTest
     , writeWriteDeadlockTest
     ]
  