packages feed

super-user-spark-0.3.0.0: test/DeployerSpec.hs

module DeployerSpec where

import           Check.Internal
import           Check.Types
import           Config
import           Config.Types
import           Data.Either           (isLeft)
import           Data.Maybe            (isNothing)
import           Deployer.Internal
import           Deployer.Types
import           Monad
import           Parser.Gen
import           System.Directory      hiding (createDirectoryIfMissing)
import           System.FilePath.Posix ((</>))
import           System.Posix.Files
import           Test.Hspec
import           Test.QuickCheck
import           Utils

spec :: Spec
spec = do
    cleanSpec
    deploymentSpec
    completionSpec

cleanSpec :: Spec
cleanSpec = do
    let sandbox = "test_sandbox"
    let setup = createDirectoryIfMissing sandbox
    let teardown = removeDirectoryRecursive sandbox

    let clean :: SparkConfig -> CleanupInstruction -> IO ()
        clean conf ci = runSparker conf (performClean ci) `shouldReturn` Right ()

    beforeAll_ setup $ afterAll_ teardown $ do
        describe "performClean" $ do

            it "doesn't remove this file if that's not in the config" $ do
                let c = defaultConfig { conf_deploy_replace_files = False }
                withCurrentDirectory sandbox $ do
                    let file = "test.txt"
                    writeFile file "This is a test"
                    diagnoseFp file `shouldReturn` IsFile
                    clean c $ CleanFile file
                    diagnoseFp file `shouldReturn` IsFile
                    removeFile file
                    diagnoseFp file `shouldReturn` Nonexistent

            it "removes this file if that's in the config" $ do
                let c = defaultConfig { conf_deploy_replace_files = True }
                withCurrentDirectory sandbox $ do
                    let file = "test.txt"
                    writeFile file "This is a test"
                    diagnoseFp file `shouldReturn` IsFile
                    clean c $ CleanFile file
                    diagnoseFp file `shouldReturn` Nonexistent

            it "doesn't remove this directory if that's not in the config" $ do
                let c = defaultConfig { conf_deploy_replace_directories = False }
                withCurrentDirectory sandbox $ do
                    let dir = "testdirectory"
                    createDirectoryIfMissing dir
                    diagnoseFp dir `shouldReturn` IsDirectory
                    clean c $ CleanDirectory dir
                    diagnoseFp dir `shouldReturn` IsDirectory
                    removeDirectoryRecursive dir
                    diagnoseFp dir `shouldReturn` Nonexistent

            it "removes this directory if that's in the config" $ do
                let c = defaultConfig { conf_deploy_replace_directories = True }
                withCurrentDirectory sandbox $ do
                    let dir = "testdirectory"
                    createDirectoryIfMissing dir
                    diagnoseFp dir `shouldReturn` IsDirectory
                    clean c $ CleanDirectory dir
                    diagnoseFp dir `shouldReturn` Nonexistent

            it "doesn't remove this link if that's not in the config" $ do
                let c = defaultConfig { conf_deploy_replace_links = False }
                withCurrentDirectory sandbox $ do
                    let link = "testlink"
                    let file = "testfile"
                    writeFile file "This is a test"
                    createSymbolicLink file link
                    diagnoseFp link `shouldReturn` IsLinkTo file
                    clean c $ CleanLink link
                    diagnoseFp link `shouldReturn` IsLinkTo file
                    removeLink link
                    diagnoseFp link `shouldReturn` Nonexistent
                    removeFile file
                    diagnoseFp file `shouldReturn` Nonexistent

            it "removes this link with an existent source if that's in the config" $ do
                let c = defaultConfig { conf_deploy_replace_links = True }
                withCurrentDirectory sandbox $ do
                    let link = "testlink"
                    let file = "testfile"
                    writeFile file "This is a test"
                    createSymbolicLink file link
                    diagnoseFp link `shouldReturn` IsLinkTo file
                    clean c $ CleanLink link
                    diagnoseFp link `shouldReturn` Nonexistent
                    removeFile file
                    diagnoseFp file `shouldReturn` Nonexistent

            it "removes this link with a nonexistent source if that's in the config" $ do
                let c = defaultConfig { conf_deploy_replace_links = True }
                withCurrentDirectory sandbox $ do
                    let link = "testlink"
                    let file = "testfile"
                    createSymbolicLink file link
                    diagnoseFp link `shouldReturn` IsLinkTo file
                    diagnoseFp file `shouldReturn` Nonexistent
                    clean c $ CleanLink link
                    diagnoseFp link `shouldReturn` Nonexistent
                    diagnoseFp file `shouldReturn` Nonexistent

deploymentSpec :: Spec
deploymentSpec = do
    let sandbox = "test_sandbox"
    let setup = createDirectoryIfMissing sandbox
    let teardown = removeDirectoryRecursive sandbox

    beforeAll_ setup $ afterAll_ teardown $ do
        describe "copy" $ do
            it "succcesfully copies this file" $ do
                withCurrentDirectory sandbox $ do
                    let src = "testfile"
                    let dst = "testcopy"
                    writeFile src "This is a file."

                    diagnoseFp src `shouldReturn` IsFile
                    diagnoseFp dst `shouldReturn` Nonexistent

                    -- Under test
                    copy src dst

                    diagnoseFp src `shouldReturn` IsFile
                    diagnoseFp dst `shouldReturn` IsFile

                    dsrc <- diagnose src
                    ddst <- diagnose dst
                    diagnosedHashDigest ddst `shouldBe` diagnosedHashDigest dsrc

                    removeFile src
                    removeFile dst

                    diagnoseFp src `shouldReturn` Nonexistent
                    diagnoseFp dst `shouldReturn` Nonexistent

            it "succcesfully copies this directory" $ do
                withCurrentDirectory sandbox $ do
                    let src = "testdir"
                    let dst = "testcopy"
                    createDirectoryIfMissing src

                    diagnoseFp src `shouldReturn` IsDirectory
                    diagnoseFp dst `shouldReturn` Nonexistent

                    -- Under test
                    copy src dst

                    diagnoseFp src `shouldReturn` IsDirectory
                    diagnoseFp dst `shouldReturn` IsDirectory

                    dsrc <- diagnose src
                    ddst <- diagnose dst
                    diagnosedHashDigest ddst `shouldBe` diagnosedHashDigest dsrc

                    removeDirectoryRecursive src
                    removeDirectoryRecursive dst

                    diagnoseFp src `shouldReturn` Nonexistent
                    diagnoseFp dst `shouldReturn` Nonexistent

        describe "link" $ do
            it "successfully links this file" $ do
                withCurrentDirectory sandbox $ do
                    let src = "testfile"
                    let dst = "testlink"

                    diagnoseFp src `shouldReturn` Nonexistent
                    diagnoseFp dst `shouldReturn` Nonexistent

                    writeFile src "This is a test."

                    diagnoseFp src `shouldReturn` IsFile
                    diagnoseFp dst `shouldReturn` Nonexistent

                    -- Under test
                    link src dst

                    diagnoseFp src `shouldReturn` IsFile
                    diagnoseFp dst `shouldReturn` IsLinkTo src

                    removeFile src
                    removeLink dst

                    diagnoseFp src `shouldReturn` Nonexistent
                    diagnoseFp dst `shouldReturn` Nonexistent

            it "successfully links this directory" $ do
                withCurrentDirectory sandbox $ do
                    let src = "testdir"
                    let dst = "testlink"

                    diagnoseFp src `shouldReturn` Nonexistent
                    diagnoseFp dst `shouldReturn` Nonexistent

                    createDirectoryIfMissing src

                    diagnoseFp src `shouldReturn` IsDirectory
                    diagnoseFp dst `shouldReturn` Nonexistent

                    -- Under test
                    link src dst

                    diagnoseFp src `shouldReturn` IsDirectory
                    diagnoseFp dst `shouldReturn` IsLinkTo src

                    removeDirectoryRecursive src
                    removeLink dst

                    diagnoseFp src `shouldReturn` Nonexistent
                    diagnoseFp dst `shouldReturn` Nonexistent


completionSpec :: Spec
completionSpec = do
    describe "complete" $ do
        -- Necessary because not all utilities can handle paths with '~' in them.
        it "replaces the home directory as specified for simple home directories and simple paths" $ do
            forAll arbitrary $ \env ->
                forAll generateWord $ \home ->
                    forAll generateWord $ \fp ->
                        complete home env ("~" </> fp) `shouldBe` Right (home </> fp)

    describe "parseId" $ do
        it "Works for these cases" $ do
            parseId "" `shouldBe` []
            parseId "file" `shouldBe` [Plain "file"]
            parseId "something$(with)variable" `shouldBe` [Plain "something", Var "with", Plain "variable"]
            parseId "$(one)$(two)$(three)" `shouldBe` [Var "one", Var "two", Var "three"]

    describe "replaceId" $ do
        it "leaves plain ID's unchanged in any environment" $ do
            forAll arbitrary $ \env ->
                forAll arbitrary $ \s ->
                    replaceId env (Plain s) `shouldBe` Right s

        it "returns Left if a variable is not in the environment" $ do
            forAll arbitrary $ \var ->
                forAll (arbitrary `suchThat` (isNothing . lookup var)) $ \env ->
                    replaceId env (Var var) `shouldSatisfy` isLeft

        it "replaces a variable if it's in the environment" $ do
            forAll arbitrary $ \var ->
                forAll arbitrary $ \val ->
                    forAll (arbitrary `suchThat` (isNothing . lookup var)) $ \env1 ->
                        forAll (arbitrary `suchThat` (isNothing . lookup var)) $ \env2 ->
                            replaceId (env1 ++ [(var, val)] ++ env2) (Var var) `shouldBe` Right val