packages feed

net-mqtt-0.8.6.0: test/DecayingSpec.hs

{-# LANGUAGE BlockArguments    #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ViewPatterns      #-}

module DecayingSpec where

import           Control.Concurrent              (threadDelay)
import           Control.Concurrent.STM          (STM, atomically)
import           Control.Monad                   (foldM, mapM_)
import qualified Data.Attoparsec.ByteString.Lazy as A
import qualified Data.ByteString.Lazy            as L
import           Data.Foldable                   (traverse_)
import qualified Data.Map.Strict                 as Map
import qualified Data.Map.Strict.Decaying        as DecayingMap
import           Data.Set                        (Set)
import qualified Data.Set                        as Set

import           Test.QuickCheck

prop_decayingMapWorks :: [Int] -> Property
prop_decayingMapWorks keys = idempotentIOProperty $ do
  m <- DecayingMap.new 60
  atomically $ traverse_ (\x -> DecayingMap.insert x x m) keys
  found <- atomically $ traverse (\x -> DecayingMap.findWithDefault maxBound x m) keys
  pure $ found === keys

prop_decayingMapDecays :: [Int] -> Property
prop_decayingMapDecays keys = idempotentIOProperty $ do
  m <- DecayingMap.new 0.001
  atomically $ traverse_ (\x -> DecayingMap.insert x x m) keys
  threadDelay 5000
  DecayingMap.tick m
  found <- atomically $ DecayingMap.elems m
  pure $ found === []

prop_decayingMapUpdates :: Set Int -> Property
prop_decayingMapUpdates (Set.toList -> keys) = idempotentIOProperty $ do
  m <- DecayingMap.new 60
  atomically $ traverse_ (\x -> DecayingMap.insert x x m) keys
  updated <- atomically $ traverse (\x -> DecayingMap.updateLookupWithKey (\_ v -> Just (v + 1)) x m) keys
  found <- atomically $ traverse (\x -> DecayingMap.findWithDefault maxBound x m) keys
  pure $ (found === fmap (+ 1) keys .&&. Just found === sequenceA updated)

prop_decayingMapDeletes :: Set Int -> Property
prop_decayingMapDeletes (Set.toList -> keys) = (not . null) keys ==> idempotentIOProperty $ do
  m <- DecayingMap.new 60
  atomically $ traverse_ (\x -> DecayingMap.insert x x m) keys
  atomically $ traverse (`DecayingMap.delete` m) (tail keys)
  found <- atomically $ DecayingMap.elems m
  pure $ found === take 1 keys