drifter-0.2.1: test/Main.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Main
( main
) where
-------------------------------------------------------------------------------
import Control.Applicative as A
import Data.IORef
import Data.List
import Data.Text (Text)
import qualified Data.Text as T
import Test.Tasty
import Test.Tasty.HUnit
import Test.Tasty.QuickCheck
-------------------------------------------------------------------------------
import Drifter
-------------------------------------------------------------------------------
main :: IO ()
main = defaultMain tests
tests :: TestTree
tests = testGroup "drifter"
[
graphTests
, typesTests
, changeSequenceTests
]
-------------------------------------------------------------------------------
changeSequenceTests :: TestTree
changeSequenceTests = testGroup "changeSequence"
[
testProperty "preserves list members" $ \((Blind cs) :: Blind [Change TestDB]) ->
let cnames = changeName <$> cs
cnames' = changeName <$> changeSequence cs
in cnames === cnames'
]
-------------------------------------------------------------------------------
graphTests :: TestTree
graphTests = testGroup "Drifter.Graph"
[
resolveDependencyOrderTests
]
typesTests :: TestTree
typesTests = testGroup "Drifter.Types"
[
migrateTests
]
resolveDependencyOrderTests :: TestTree
resolveDependencyOrderTests = testGroup "resolveDependencyOrder"
[
testProperty "orders by dependency" $ \(UniqueChanges cs) ->
let presorted = changeSequence cs
in resolveDependencyOrder presorted === presorted
]
migrateTests :: TestTree
migrateTests = testGroup "migrate"
[
testCase "runs the given migrations" $ do
runs <- newIORef []
_ <- migrate (DBConnection $ TestDBConn runs) exampleChanges
res <- readIORef runs
res @?= [1,2,3]
]
exampleChanges :: [Change TestDB]
exampleChanges = [c2, c3, c1]
where
c1 = Change c1n Nothing [] (RunMigrationNumber 1)
c1n = ChangeName "c1"
c2n = ChangeName "c2"
c3n = ChangeName "c3"
c2 = c1 { changeName = c2n, changeDependencies = [c1n], changeMethod = RunMigrationNumber 2}
c3 = c1 { changeName = c3n, changeDependencies = [c2n], changeMethod = RunMigrationNumber 3}
data TestDB
newtype TestDBConn = TestDBConn (IORef [Int])
data instance Method TestDB = RunMigrationNumber Int deriving (Show, Eq)
data instance DBConnection TestDB = DBConnection TestDBConn
instance Drifter TestDB where
migrateSingle (DBConnection (TestDBConn runs)) Change { changeMethod = RunMigrationNumber mn} = do
modifyIORef runs (++ [mn])
return $ Right ()
instance Arbitrary Text where
arbitrary = T.pack <$> arbitrary
deriving instance Arbitrary ChangeName
instance Arbitrary (Method TestDB) where
arbitrary = RunMigrationNumber <$> arbitrary
instance Arbitrary (Change TestDB) where
arbitrary = Change <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
deriving instance Eq (Change TestDB)
deriving instance Show (Change TestDB)
newtype UniqueChanges = UniqueChanges [Change TestDB] deriving (Show)
instance Arbitrary UniqueChanges where
arbitrary = UniqueChanges A.<$> arbitrary `suchThat` uniqueNames
where
uniqueNames cs = let names = map changeName cs
in nub names == names