packages feed

prolens-0.0.0.1: test/Test/Prolens/Inspection.hs

{-# LANGUAGE TemplateHaskell #-}

{- | Performance tests for @prolens@. Uses the @inspection-testing@
library to make sure that lenses are as efficient as manual record
getters and update syntax.
-}

module Test.Prolens.Inspection
    ( inspectionSpecs
    ) where

import Test.Hspec (Spec, describe, it, shouldSatisfy)
import Test.Inspection (Result (..), hasNoTypeClasses, inspectTest, (===))

import Prolens (preview, set, view)
import Test.Data (Grade (..), Haskeller (..), Knowledge (..), _Mark, knowledgeL, nameL, syntaxL)


setNameViaLens :: Haskeller -> Haskeller
setNameViaLens = set nameL "Dmitrii"

setNameManually :: Haskeller -> Haskeller
setNameManually h = h { haskellerName = "Dmitrii" }

getNameViaLens :: Haskeller -> String
getNameViaLens = view nameL

getNameManually :: Haskeller -> String
getNameManually (Haskeller name _ _) = name

setSyntaxViaLens :: Haskeller -> Haskeller
setSyntaxViaLens = set (knowledgeL . syntaxL) True

setSyntaxManually :: Haskeller -> Haskeller
setSyntaxManually h = h { haskellerKnowledge = (haskellerKnowledge h) { kSyntax = True } }

getSyntaxViaLens :: Haskeller -> Bool
getSyntaxViaLens = view (knowledgeL . syntaxL)

getSyntaxManually :: Haskeller -> Bool
getSyntaxManually (Haskeller _ _ (Knowledge syntax _ _ _ _)) = syntax

inspectionSpecs :: Spec
inspectionSpecs = describe "Performance Inspection Testing" $ do
    lensSpecs
    prismSpecs

lensSpecs :: Spec
lensSpecs = describe "Lens" $ do
    describe "set" $ do
        it "setting single via lens is efficient as manual record update" $
            $(inspectTest $ 'setNameViaLens === 'setNameManually) `shouldSatisfy` isSuccess
        it "setting single via lens doesn't have intermediate typeclasses" $
            $(inspectTest $ hasNoTypeClasses 'setNameViaLens) `shouldSatisfy` isSuccess
        it "setting composition via lens is efficient as manual record update" $
            $(inspectTest $ 'setSyntaxViaLens === 'setSyntaxManually) `shouldSatisfy` isSuccess
        it "setting composition via lens doesn't have intermediate typeclasses" $
            $(inspectTest $ hasNoTypeClasses 'setSyntaxViaLens) `shouldSatisfy` isSuccess
    describe "view" $ do
        it "getting single via lens is efficient as plain record function" $
            $(inspectTest $ 'getNameViaLens === 'getNameManually) `shouldSatisfy` isSuccess
        it "getting single via lens doesn't have intermediate typeclasses" $
            $(inspectTest $ hasNoTypeClasses 'getNameViaLens) `shouldSatisfy` isSuccess
        it "getting composition via lens is efficient as plain record function" $
            $(inspectTest $ 'getSyntaxViaLens === 'getSyntaxManually) `shouldSatisfy` isSuccess
        it "getting composition via lens doesn't have intermediate typeclasses" $
            $(inspectTest $ hasNoTypeClasses 'getSyntaxViaLens) `shouldSatisfy` isSuccess

matchMarkPrism :: Grade -> Maybe Int
matchMarkPrism = preview _Mark

matchMarkManual :: Grade -> Maybe Int
matchMarkManual grade = case grade of
    Mark n -> Just n
    _other -> Nothing

prismSpecs :: Spec
prismSpecs = describe "Prism" $ do
    describe "preview" $ do
        it "preview _Ctor x ≡ case (Ctor _) of" $
            $(inspectTest $ 'matchMarkPrism === 'matchMarkManual) `shouldSatisfy` isSuccess

-- Helper functions

isSuccess :: Result -> Bool
isSuccess (Success _) = True
isSuccess (Failure _) = False