packages feed

xfconf-4.8.0.0: Tests/Tests.hs

{-| some tests you can run with `runghc -lxfconf-0 Tests/Tests` -}
-- A rewrite of the previous tests using monadic quickcheck

module Main where

import Test.Framework                       (defaultMain, testGroup)
import Test.Framework.Providers.HUnit
import Test.Framework.Providers.QuickCheck2
import Test.HUnit

import Test.QuickCheck
import Test.QuickCheck.Monadic              as QCM

import Control.Concurrent                   (threadDelay)
import Data.Char                            (toLower)
import Text.Printf

import System.XFCE.Xfconf

myChannel = "QuickCheck"

main :: IO ()
main = defaultMain testSuite

  -- we need to sleep because garbace collection must collect objects
  -- before we shutdown xfconf (!! this sucks !!)
  where msleep = threadDelay . (1000*)

testSuitv = [ testGroup "Debugging"
                    [ testStringList
                    ]
            ]

testSuite = [ testGroup "QuickCheck"
                    [ testChannelPropertyBase
                    , testXfconfValue
                    , testXfconfArray
                    , testStringList
                    , testStringArray
                    , testString
                    , testDouble
                    , testInt
                    , testUInt
                    , testInt16
                    , testUInt16
                    , testUInt64
                    , testBool
                    ]
            , testGroup "HUnit"
                    [ testChannels
                    , testHasProperty
                    , testPropertyLocked
                    , testGetKeys
                    , testGetProperties
                    , testResetProperties
                    , testChannelName
                    ]
            ]

-- | Really dumb test
testChannels = testCase "xfconf_list_channels" $ do
        putStrLn "  Available channels:"

        xfconfListChannels >>= printStringArray

        assertBool "Query list of channels" True

testHasProperty = testCase "xfconf_channel_has_property" $ do
        chan  <- channelGet "xfce4-desktop"
        dummy <- channelHasProperty chan "/no/property"
        img   <- channelHasProperty chan "/backdrop/screen0/monitor0/image-path"

        assertBool "Non-existing property" (dummy == False)
        assertBool "Existing property" (img == True)

testPropertyLocked = testCase "xfconf_channel_is_property_locked" $ do
        chan  <- channelGet "xsettings"
        value <- channelIsPropertyLocked chan "/Net/ThemeName"

        assertBool "Property should not be locked" (value == False)

testResetProperties = testCase "xfconf_channel_reset_property" $ do
        chan  <- channelGet "QuickCheck"
        channelResetProperty chan "/" True
        alist <- chan `channelGetProperties` "/"

        assertBool "Channel not empty" (null alist)

testChannelName = testCase "channel attribute name" $ do
        let name = myChannel
        name'   <- channelGetName =<< channelGet name
        name''  <- channelGetName =<< channelNew name
        name''' <- channelGetName =<< channelNewWithPropertyBase name "/foo"

        assertBool "channelGet name"                 (name === name')
        assertBool "channelNew name"                 (name === name'')
        assertBool "channelNewWithPropertyBase name" (name === name''')

  where s === s' = lower s == lower s'
        lower = map toLower


{----------------------------------------------------------------------
-- Serious business goes here
-- (well, it was serious because I had to implement GHashTable bindings)
----------------------------------------------------------------------}

testGetKeys =
  testCase "listing keys from a GHashTable" $ do
        putStrLn "  xfce4-desktop keys list:"

        desktop <- channelGet "xfce4-desktop"
        channelGetKeys desktop "/" >>= printStringArray

        assertBool "Query list of channel keys" True

testGetProperties =
  testCase "listing properties from a GHashTable" $ do
        putStrLn "  QuickCheck properties list:"

        desktop <- channelGet "QuickCheck"
        channelGetProperties desktop "/" >>= printTuples

        assertBool "Query list of channel properties" True


{----------------------------------------------------------------------
-- QuickCheck.v2
----------------------------------------------------------------------}

testChannelPropertyBase =
  testProperty "channel attribute property base" $ monadicIO $ do
          base  <- pick genAsciiString
          chan  <- QCM.run $ channelNewWithPropertyBase myChannel base
          base' <- QCM.run $ channelGetPropertyBase chan

          QCM.assert (base' == base)

-- | garbage string, just be careful to avoid C-String delimiter ('\0')
genUTFString :: Gen String
genUTFString = suchThat arbitrary (notElem '\0')

genAsciiString :: Gen String
genAsciiString = listOf1 (elements ascii)
  where ascii = ['a'..'z'] ++ ['A'..'Z'] ++ ['0'..'9'] ++ " \t"

-- Warnings:
--
-- XfconfStringList [String] are returned as
-- XfconfArray [XfconfString s]
--
-- (U)Int16 are returned as plain (U)Int by xfconfd
genBasicXfconfValue :: Gen XfconfValue
genBasicXfconfValue = oneof [ XfconfString `fmap` genUTFString
                            , XfconfInt    `fmap` arbitrary
                            , XfconfUInt   `fmap` arbitrarySizedIntegral
                            , XfconfUInt64 `fmap` arbitrarySizedIntegral
                            , XfconfDouble `fmap` arbitrary
                            , XfconfBool   `fmap` arbitrary
                            ]

testXfconfValue = testValue "XfconfValue"
                            -- setProperty Nothing is cursed by the
                            -- monomorphism restriction
                            (Just `fmap` genBasicXfconfValue)
                            channelGetProperty
                            channelSetProperty
testXfconfArray = testValue "XfconfArray"
                            (listOf genBasicXfconfValue)
                            channelGetArray
                            channelSetArray
testStringArray = testValue "StringArray"
                            (listOf genUTFString)
                            channelGetStringArray
                            channelSetStringList
  -- We will re-use our 'testValue' function but since it expect the Get
  -- and Set operator to work with the same type, we provide an hackish
  -- function to convert an XfconfArray [XfconfString] to [String]
  where channelGetStringArray :: XfconfChannel -> String -> IO [String]
        channelGetStringArray ch prop = do
           r <- channelGetProperty ch prop
           case r of
                Just (XfconfArray v) -> return (map fromXfconfString v)
                Nothing -> return []
                _       -> error "internal error"

        fromXfconfString (XfconfString s) = s
        fromXfconfString _                = error "expect XfconfString"

testStringList  = testValue "StringList"
                            (listOf genUTFString)
                            channelGetStringList
                            channelSetStringList
testString      = testValue "String"
                            genUTFString
                            channelGetString
                            channelSetString
testDouble      = testValue "Double"
                            arbitrary
                            channelGetDouble
                            channelSetDouble
testInt         = testValue "Int"
                            arbitrary
                            channelGetInt
                            channelSetInt
testUInt        = testValue "UInt"
                            arbitrarySizedIntegral
                            channelGetUInt
                            channelSetUInt
testInt16       = testValue "Int16"
                            arbitrarySizedIntegral
                            channelGetInt16
                            channelSetInt16
testUInt16      = testValue "UInt16"
                            arbitrarySizedIntegral
                            channelGetUInt16
                            channelSetUInt16
testUInt64      = testValue "UInt64"
                            arbitrarySizedIntegral
                            channelGetUInt64
                            channelSetUInt64
testBool        = testValue "Bool"
                            arbitrary
                            channelGetBool
                            channelSetBool

-- | Check generic read and write operations
testValue typeName gen getOp setOp =
  testProperty testName $ QCM.monadicIO $ do

        value  <- QCM.pick gen
        value' <- QCM.run $ computeNewValue value
        QCM.assert (value == value')

  where testName = "xfconf_channel_get/set " ++ typeName
        computeNewValue v= do
                -- we use the name of the type as xfconf property name
                let prop = "/" ++ typeName
                channel <- channelGet myChannel

                -- apply dummy test value
                setOp channel prop v
                -- Query xfconfd back
                getOp channel prop


manualTestProperty setOp getOp value = do
    channel <- channelGet myChannel
    setOp channel prop value
    value' <- getOp channel prop
    let same = (value == value')
    if same
       then printf "Ok\n"
       else printf "(value,value') = (%s, %s)\n" (show value) (show value')

  where prop = "/Manual"

{----------------------------------------------------------------------
-- Utilities
----------------------------------------------------------------------}

-- | Pretty print function because I am getting bored watching tests
-- output
printStringArray :: [String] -> IO ()
printStringArray xs = mapM_ (\x -> putStrLn ("    " ++ show x)) xs

printTuples :: [(String, Maybe XfconfValue)] -> IO ()
printTuples xs = mapM_ fmt xs
  where fmt (k,v) = putStrLn $ "    " ++ k ++ ": " ++ show v