packages feed

large-anon-0.2: test/Test/Sanity/OverloadedRecordUpdate.hs

{-# LANGUAGE CPP #-}

#if __GLASGOW_HASKELL__ < 902

module Test.Sanity.OverloadedRecordUpdate (tests) where

import Test.Tasty
import Test.Tasty.HUnit

tests :: TestTree
tests =
    testCaseInfo "Test.Sanity.OverloadedRecordUpdate" $
      return "Skipped for ghc < 9.2"

#else

{-# LANGUAGE DataKinds              #-}
{-# LANGUAGE NamedFieldPuns         #-}
{-# LANGUAGE OverloadedRecordDot    #-}
{-# LANGUAGE OverloadedRecordUpdate #-}
{-# LANGUAGE RebindableSyntax       #-}
{-# LANGUAGE TypeOperators          #-}

{-# OPTIONS_GHC -fplugin=Data.Record.Anon.Plugin #-}

module Test.Sanity.OverloadedRecordUpdate (tests) where

import Test.Tasty
import Test.Tasty.HUnit

import Data.Record.Anon
import Data.Record.Anon.Overloading

import qualified Data.Record.Anon.Simple   as S
import qualified Data.Record.Anon.Advanced as A

tests :: TestTree
tests = testGroup "Test.Sanity.OverloadedRecordUpdate" [
      testGroup "Simple" [
          testCase "topLevel" test_simple_topLevel
        , testCase "nested"   test_simple_nested
        , testCase "punned"   test_simple_punned
        ]
    , testGroup "Advanced" [
          testCase "topLevel" test_advanced_topLevel
        , testCase "nested"   test_advanced_nested
        , testCase "punned"   test_advanced_punned
        ]
    ]

{-------------------------------------------------------------------------------
  Simple API
-------------------------------------------------------------------------------}

test_simple_topLevel :: Assertion
test_simple_topLevel = do
    assertEqual "" expected $
      r { a = 6 }
  where
    r, expected :: S.Record [ "a" := Int, "b" := Bool ]
    r        = ANON { a = 5, b = True }
    expected = ANON { a = 6, b = True }

-- NOTE: nested updates rely on OverloadedRecordDot in addition to
-- OverloadedRecordUpdate.
test_simple_nested :: Assertion
test_simple_nested = do
    assertEqual "" expected $
      r{b.c = False}
  where
    r, expected :: S.Record [ "a" := Int, "b" := S.Record [ "c" := Bool, "d" := Char ] ]
    r        = ANON { a = 5, b = ANON { c = True,  d = 'a' } }
    expected = ANON { a = 5, b = ANON { c = False, d = 'a' } }

test_simple_punned :: Assertion
test_simple_punned =
    assertEqual "" expected $
      let c = False in r{b.c}
  where
    r, expected :: S.Record [ "a" := Int, "b" := S.Record [ "c" := Bool, "d" := Char ] ]
    r        = ANON { a = 5, b = ANON { c = True,  d = 'a' } }
    expected = ANON { a = 5, b = ANON { c = False, d = 'a' } }

{-------------------------------------------------------------------------------
  Advanced API
-------------------------------------------------------------------------------}

test_advanced_topLevel :: Assertion
test_advanced_topLevel = do
    assertEqual "" expected $
      r { a = Nothing }
  where
    r, expected :: A.Record Maybe [ "a" := Int, "b" := Bool ]
    r        = ANON_F { a = Just 5,  b = Just True }
    expected = ANON_F { a = Nothing, b = Just True }

test_advanced_nested :: Assertion
test_advanced_nested = do
    assertEqual "" expected $
      r{b.d = Just 'a'}
  where
    r, expected :: S.Record [ "a" := Int, "b" := A.Record Maybe [ "c" := Bool, "d" := Char ] ]
    r        = ANON { a = 5, b = ANON_F { c = Just True, d = Nothing  } }
    expected = ANON { a = 5, b = ANON_F { c = Just True, d = Just 'a' } }

test_advanced_punned :: Assertion
test_advanced_punned = do
    assertEqual "" expected $
      let d = Just 'a' in r{b.d}
  where
    r, expected :: S.Record [ "a" := Int, "b" := A.Record Maybe [ "c" := Bool, "d" := Char ] ]
    r        = ANON { a = 5, b = ANON_F { c = Just True, d = Nothing  } }
    expected = ANON { a = 5, b = ANON_F { c = Just True, d = Just 'a' } }

#endif