{-# LANGUAGE TemplateHaskell #-} -- Copyright (C) 2010-2012 John Millikin -- -- This program is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . module DBusTests.Introspection (test_Introspection) where import Test.Chell import Test.Chell.QuickCheck import Test.QuickCheck hiding (property) import Control.Applicative ((<$>), (<*>)) import Control.Monad (liftM, liftM2) import DBus import qualified DBus.Introspection as Introspection import DBusTests.InterfaceName () import DBusTests.MemberName () import DBusTests.ObjectPath () import DBusTests.Signature () import DBusTests.Util (halfSized) test_Introspection :: Suite test_Introspection = suite "Introspection" [ test_XmlPassthrough , test_XmlParse , test_XmlParseFailed , test_XmlWriteFailed ] test_XmlPassthrough :: Test test_XmlPassthrough = property "xml-passthrough" $ \obj -> let path = Introspection.objectPath obj Just xml = Introspection.formatXML obj in Introspection.parseXML path xml == Just obj test_XmlParse :: Test test_XmlParse = assertions "xml-parse" $ do -- root object path can be inferred $expect (equal (Introspection.parseXML (objectPath_ "/") "") (Just (Introspection.object (objectPath_ "/")) { Introspection.objectChildren = [ Introspection.object (objectPath_ "/foo") ] } )) test_XmlParseFailed :: Test test_XmlParseFailed = assertions "xml-parse-failed" $ do $expect (nothing (Introspection.parseXML (objectPath_ "/") "")) $expect (nothing (Introspection.parseXML (objectPath_ "/") "")) -- invalid property access $expect (nothing (Introspection.parseXML (objectPath_ "/") "\ \ \ \ \ \ \ \ \ \")) -- invalid parameter type $expect (nothing (Introspection.parseXML (objectPath_ "/") "\ \ \ \ \ \ \ \ \ \ \ \")) test_XmlWriteFailed :: Test test_XmlWriteFailed = assertions "xml-write-failed" $ do -- child's object path isn't under parent's $expect (nothing (Introspection.formatXML (Introspection.object (objectPath_ "/foo")) { Introspection.objectChildren = [ Introspection.object (objectPath_ "/bar") ] })) -- invalid type $expect (nothing (Introspection.formatXML (Introspection.object (objectPath_ "/foo")) { Introspection.objectInterfaces = [ (Introspection.interface (interfaceName_ "/bar")) { Introspection.interfaceProperties = [ Introspection.property "prop" (TypeDictionary TypeVariant TypeVariant) ] } ] })) instance Arbitrary Type where arbitrary = oneof [atom, container] where atom = elements [ TypeBoolean , TypeWord8 , TypeWord16 , TypeWord32 , TypeWord64 , TypeInt16 , TypeInt32 , TypeInt64 , TypeDouble , TypeString , TypeObjectPath , TypeSignature ] container = oneof [ return TypeVariant , liftM TypeArray arbitrary , liftM2 TypeDictionary atom arbitrary , liftM TypeStructure (listOf1 (halfSized arbitrary)) ] instance Arbitrary Introspection.Object where arbitrary = arbitrary >>= subObject subObject :: ObjectPath -> Gen Introspection.Object subObject parentPath = sized $ \n -> resize (min n 4) $ do let nonRoot = do x <- resize 10 arbitrary case formatObjectPath x of "/" -> nonRoot x' -> return x' thisPath <- nonRoot let path' = case formatObjectPath parentPath of "/" -> thisPath x -> x ++ thisPath let path = objectPath_ path' ifaces <- arbitrary children <- halfSized (listOf (subObject path)) return (Introspection.object path) { Introspection.objectInterfaces = ifaces , Introspection.objectChildren = children } instance Arbitrary Introspection.Interface where arbitrary = do name <- arbitrary methods <- arbitrary signals <- arbitrary properties <- arbitrary return (Introspection.interface name) { Introspection.interfaceMethods = methods , Introspection.interfaceSignals = signals , Introspection.interfaceProperties = properties } instance Arbitrary Introspection.Method where arbitrary = do name <- arbitrary args <- arbitrary return (Introspection.method name) { Introspection.methodArgs = args } instance Arbitrary Introspection.Signal where arbitrary = do name <- arbitrary args <- arbitrary return (Introspection.signal name) { Introspection.signalArgs = args } instance Arbitrary Introspection.MethodArg where arbitrary = Introspection.methodArg <$> gen_Ascii <*> arbitrary <*> arbitrary instance Arbitrary Introspection.Direction where arbitrary = elements [Introspection.directionIn, Introspection.directionOut] instance Arbitrary Introspection.SignalArg where arbitrary = Introspection.signalArg <$> gen_Ascii <*> arbitrary instance Arbitrary Introspection.Property where arbitrary = do name <- gen_Ascii t <- arbitrary canRead <- arbitrary canWrite <- arbitrary return (Introspection.property name t) { Introspection.propertyRead = canRead , Introspection.propertyWrite = canWrite } gen_Ascii :: Gen String gen_Ascii = listOf (elements ['!'..'~'])