packages feed

app-settings-0.2.0.4: tests/Tests.hs

{-# LANGUAGE ScopedTypeVariables #-}

import Data.AppSettings
import Data.AppSettingsInternal

import Test.Hspec
import Test.HUnit (assertBool, assertEqual)

import System.Directory (removeFile, copyFile, doesFileExist)
import Control.Exception (try, SomeException)

textSizeFromWidth :: Setting Double
textSizeFromWidth = Setting "textSizeFromWidth" 0.04

textFill :: Setting (Double,Double,Double,Double)
textFill = Setting "textFill" (1, 1, 0, 1)

textSizeFromHeight :: Setting Double
textSizeFromHeight = Setting "textSizeFromHeight" 12.4

testInlineList :: Setting [String]
testInlineList = Setting "testInlineList" ["inline1", "inline2", "inline3"]

testList :: Setting [String]
testList = ListSetting "testList" ["list1", "list2", "list3"]

defaultConfig :: DefaultConfig
defaultConfig = getDefaultConfig $ do
	setting textSizeFromWidth
	setting textSizeFromHeight
	setting textFill
	setting testInlineList
	setting testList

main :: IO ()
main = hspec $ do
	describe "unit tests" testIsKeyForListSetting
	describe "load config" $ do
		testEmptyFileDefaults
		testPartialFileDefaults
		testPartialFileDefaults2
		testFileWithComments
		testInvalidFile
		testInvalidValue
		testNonExistingFile
		testReadLongSetting
	describe "save config" $ do
		testSaveUserSetAndDefaults
		createBakBeforeSaving
		wrapLongSettings
	describe "set setting" testSetListSetting

testEmptyFileDefaults :: Spec
testEmptyFileDefaults = it "parses correctly an empty file with defaults" $ do
    readResult <- try $ readSettings (Path "tests/empty.config")
    case readResult of
    	Right (_, GetSetting getSetting) -> do
    		getSetting textSizeFromWidth `shouldBe` 0.04
    		getSetting textSizeFromHeight `shouldBe` 12.4
    		getSetting textFill `shouldBe` (1,1,0,1)
    		getSetting testInlineList `shouldBe` ["inline1", "inline2", "inline3"]
    		getSetting testList `shouldBe` ["list1", "list2", "list3"]
    	Left (x :: SomeException) -> assertBool (show x) False

testPartialFileDefaults :: Spec
testPartialFileDefaults = it "parses correctly a partial file with defaults" $ do
    readResult <- try $ readSettings (Path "tests/partial.config")
    case readResult of
    	Right (_, GetSetting getSetting) -> do
    		getSetting textSizeFromWidth `shouldBe` 1.02
    		getSetting textSizeFromHeight `shouldBe` 12.4
    		getSetting textFill `shouldBe` (1,2,3,4)
    		getSetting testInlineList `shouldBe` ["un", "deux"]
    		getSetting testList `shouldBe` ["one", "two"]
    	Left (x :: SomeException) -> assertBool (show x) False

testPartialFileDefaults2 :: Spec
testPartialFileDefaults2 = it "parses correctly a partial2 file with defaults" $ do
    readResult <- try $ readSettings (Path "tests/partial2.config")
    case readResult of
    	Right (_, GetSetting getSetting) -> do
    		getSetting textSizeFromWidth `shouldBe` 1.02
    		getSetting textSizeFromHeight `shouldBe` 12.4
    		getSetting textFill `shouldBe` (1,2,3,4)
    		getSetting testInlineList `shouldBe` ["un", "deux"]
    		getSetting testList `shouldBe` []
    	Left (x :: SomeException) -> assertBool (show x) False

testFileWithComments :: Spec
testFileWithComments = it "parses correctly a partial file with comments" $ do
    readResult <- try $ readSettings (Path "tests/test-save.txt")
    case readResult of
    	Right (_, GetSetting getSetting) -> do
    		getSetting textSizeFromWidth `shouldBe` 1.02
    		getSetting textSizeFromHeight `shouldBe` 12.4
    		getSetting textFill `shouldBe` (1,2,3,4)
    		getSetting testInlineList `shouldBe` ["un", "deux"]
    		getSetting testList `shouldBe` ["one", "two"]
    	Left (x :: SomeException) -> assertBool (show x) False

testInvalidValue :: Spec
testInvalidValue = it "parses correctly a file with invalid values" $ do
    readResult <- try $ readSettings (Path "tests/brokenvalue.config")
    case readResult of
    	Right (_, GetSetting getSetting) -> do
    		-- give the default for the invalid value
    		getSetting textSizeFromWidth `shouldBe` 0.04
    		getSetting textSizeFromHeight `shouldBe` 12.4
    		getSetting textFill `shouldBe` (1,2,3,4)
    		getSetting testInlineList `shouldBe` ["inline1", "inline2", "inline3"]
    		getSetting testList `shouldBe` ["list1", "list2", "list3"]
    	Left (x :: SomeException) -> assertBool (show x) False

testNonExistingFile :: Spec
testNonExistingFile = it "returns empty config for a non-existing file" $ do
	readResult <- try $ readSettings (Path "tests/dontexist.conf")
	case readResult of
		Right (_, GetSetting getSetting) -> do
			getSetting textSizeFromWidth `shouldBe` 0.04
			getSetting textSizeFromHeight `shouldBe` 12.4
			getSetting textFill `shouldBe` (1,1,0,1)
			getSetting testInlineList `shouldBe` ["inline1", "inline2", "inline3"]
			getSetting testList `shouldBe` ["list1", "list2", "list3"]
		Left (x :: SomeException) -> assertBool (show x) False

testReadLongSetting :: Spec
testReadLongSetting = it "Reads setting files with setting values wrapped over several lines" $ do
	readResult <- try $ readSettings (Path "tests/longsetting.conf") 
	case readResult of 
		Right (_, GetSetting getVal) -> do
			let expected = replicate 20 "longstring"
			let actual = getVal testInlineList
			assertEqual "doesn't match" expected actual
		Left (x :: SomeException) -> assertBool (show x) False

testInvalidFile :: Spec
testInvalidFile = it "reports errors properly for invalid files" $ do
    readResult <- try $ readSettings (Path "tests/broken.config")
    case readResult of
    	Left (_ :: SomeException) -> assertBool "ok" True
    	Right _ -> assertBool "did not get an error!" False

testSaveUserSetAndDefaults :: Spec
testSaveUserSetAndDefaults = it "saves a file with user-set and default settings" $ do
	readResult <- try $ readSettings (Path "tests/partial.config") 
	case readResult of 
		Right (conf, _) -> do
			saveSettings defaultConfig (Path "test.txt") conf
			actual <- readFile "test.txt"
			reference <- readFile "tests/test-save.txt"
			actual `shouldBe` reference
			removeFile "test.txt"
		Left (x :: SomeException) -> assertBool (show x) False

createBakBeforeSaving :: Spec
createBakBeforeSaving = it "creates a backup of the config file before overwriting it" $ do
	readResult <- try $ readSettings (Path "tests/partial.config") 
	case readResult of 
		Right (conf, _) -> do
			copyFile "tests/partial.config" "p.config"
			saveSettings defaultConfig (Path "p.config") conf
			doesFileExist "p.config.bak" >>= flip shouldBe True
			doesFileExist "p.config" >>= flip shouldBe True
			removeFile "p.config"
			removeFile "p.config.bak"
		Left (x :: SomeException) -> assertBool (show x) False

wrapLongSettings :: Spec
wrapLongSettings = it "wraps long settings when saving" $ do
	readResult <- try $ readSettings (Path "tests/partial.config") 
	case readResult of 
		Right (conf, _) -> do
			let conf1 = setSetting conf testInlineList $ replicate 20 "longstring"
			saveSettings defaultConfig (Path "xx.config") conf1
			expected <- readFile "tests/longsetting.conf"
			actual <- readFile "xx.config"
			assertEqual "doesn't match" expected actual
			removeFile "xx.config"
		Left (x :: SomeException) -> assertBool (show x) False
	

testSetListSetting :: Spec
testSetListSetting = it "overwrites correctly a list setting" $ do
    readResult <- try $ readSettings (Path "tests/empty.config")
    case readResult of
    	Right (conf, GetSetting getSetting) -> do
    		getSetting testList `shouldBe` ["list1", "list2", "list3"]
    		getSetting testInlineList `shouldBe` ["inline1", "inline2", "inline3"]
    		let conf0 = setSetting conf testList ["un"]
    		let conf1 = setSetting conf0 testInlineList ["one"]
    		getSetting' conf1 testList `shouldBe` ["un"]
    		getSetting' conf1 testInlineList `shouldBe` ["one"]
    		let conf2 = setSetting conf1 testList []
    		let conf3 = setSetting conf2 testInlineList []
    		getSetting' conf3 testList `shouldBe` []
    		getSetting' conf3 testInlineList `shouldBe` []
    	Left (x :: SomeException) -> assertBool (show x) False

testIsKeyForListSetting :: Spec
testIsKeyForListSetting = it "checks correctly whether a key is attached to a list setting" $ do
	isKeyForListSetting "listTest" "listTest_1" `shouldBe` True
	isKeyForListSetting "listTest" "listTest_13" `shouldBe` True
	isKeyForListSetting "listTest" "listTest_unrelated" `shouldBe` False
	isKeyForListSetting "listTest" "listTest_1notanumber" `shouldBe` False
	isKeyForListSetting "listTest" "listTestX_1" `shouldBe` False