Skip to content
Snippets Groups Projects
SpecPersistence.hs 2.75 KiB
Newer Older
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}

--
-- Test suite related to the persistence system.
--

module SpecPersistence where

import Test.QuickCheck
  ( Property
  , (===)
  )
import Control.Monad.IO.Class
  ( liftIO
  )
import Test.QuickCheck.Monadic
  ( monadicIO
  , run
  , assert
  , pre
  )
import PaymentServer.Persistence
  ( RedeemError(NotPaid, AlreadyRedeemed)
  , Voucher
  , Fingerprint
  , VoucherDatabase(payForVoucher, redeemVoucher)
  , memory
  )

-- | A voucher which has not been paid for cannot be redeemed.
unpaidVoucherNotRedeemable :: VoucherDatabase d => IO d -> Voucher -> Fingerprint -> Property
unpaidVoucherNotRedeemable getDB voucher fingerprint = monadicIO $ do
  db <- liftIO getDB
  result <- run $ redeemVoucher db voucher fingerprint
  assert (result == Left NotPaid)

-- | The in-memory implementation for unpaidVoucherNotRedeemable.
prop_memory_unpaidVoucherNotRedeemable = unpaidVoucherNotRedeemable memory

-- | A voucher which is paid for can be redeemed with any fingerprint.
paidVoucherRedeemable :: VoucherDatabase d => IO d -> Voucher -> Fingerprint -> Property
paidVoucherRedeemable getDB voucher fingerprint = monadicIO $ do
  db <- liftIO getDB
  () <- run $ payForVoucher db voucher
  result <- run $ redeemVoucher db voucher fingerprint
  assert (result == Right ())

-- | The in-memory implementation for paidVoucherRedeemable.
prop_memory_paidVoucherRedeemable = paidVoucherRedeemable memory

-- | A voucher which is paid for can be redeemed more than once as long as the
-- same fingerprint is used each time.
paidVoucherMultiRedeemable :: VoucherDatabase d => IO d -> Voucher -> Fingerprint -> Property
paidVoucherMultiRedeemable getDB voucher fingerprint = monadicIO $ do
  db <- liftIO getDB
  () <- run $ payForVoucher db voucher
  let redeem = redeemVoucher db voucher fingerprint
  run redeem
  result <- run redeem
  assert (result == Right ())

-- | The in-memory implementation for paidVoucherMultiRedeemable.
prop_memory_paidVoucherMultiRedeemable = paidVoucherMultiRedeemable memory

-- | A voucher which is paid for can not be redeemed a second time with a
-- different fingerprint than was used on the first attempt.
paidVoucherMismatchFingerprint :: VoucherDatabase d => IO d -> Voucher -> Fingerprint -> Fingerprint -> Property
paidVoucherMismatchFingerprint getDB voucher fingerprint fingerprint' = monadicIO $ do
  pre (fingerprint /= fingerprint')
  db <- liftIO getDB
  () <- run $ payForVoucher db voucher
  let redeem = redeemVoucher db voucher
  run $ redeem fingerprint
  result <- run $ redeem fingerprint'
  assert (result == Left AlreadyRedeemed)

-- | The in-memory implementation for paidVoucherMismatchFingerprint.
prop_memory_paidVoucherMismatchFingerprint = paidVoucherMismatchFingerprint memory