-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Automated Mutation Testing -- -- This package defines a mutation analysis library for haskell programs. -- It does this by parsing the haskell source, and replacing a few of the -- common haskell functions and operators with other, but similar -- operators and functions, and running the testsuite to check whether -- the difference has been detected. @package MuCheck @version 0.2.0.0 module Test.MuCheck.Utils.Print -- | simple wrapper for adding a % at the end. (./.) :: (Show a, Integral a) => a -> a -> String -- | join lines together showAS :: [String] -> String -- | make lists into lines in text. showA :: Show a => [a] -> String tt :: Show a => a -> a catchOutput :: IO a -> IO (a, String) module Test.MuCheck.MuOp data MuOp class Mutable a (==>) :: Mutable a => a -> a -> MuOp (==>*) :: Mutable a => a -> [a] -> [MuOp] (*==>*) :: Mutable a => [a] -> [a] -> [MuOp] (~~>) :: (MonadPlus m, Eq a) => a -> a -> a -> m a mkMp' :: (MonadPlus m, Typeable a) => MuOp -> a -> m a -- | The function same applies on a MuOP determining if -- transformation is between same values. same :: MuOp -> Bool instance Eq MuOp instance Mutable GuardedRhs instance Mutable Literal instance Mutable Decl instance Mutable Exp instance Mutable QOp instance Mutable QName instance Mutable Name instance Show MuOp -- | SYB functions module Test.MuCheck.Utils.Syb -- | The function relevantOps does two filters. For the first, it -- removes spurious transformations like "Int 1 ~~> Int 1". Secondly, -- it tries to apply the transformation to the given program on some -- element if it does not succeed, then we discard that transformation. relevantOps :: (Data a, Eq a) => a -> [MuOp] -> [MuOp] -- | apply a mutating function on a piece of code one at a time like -- somewhere (from so) once :: MonadPlus m => GenericM m -> GenericM m module Test.MuCheck.TestAdapter type InterpreterOutput a = Either InterpreterError (String, a) type MutantFilename = String newtype Summary Summary :: String -> Summary class Typeable s => Summarizable s where isFailure = not . isSuccess isOther x = not (isSuccess x) && not (isFailure x) testSummary :: Summarizable s => [MutantFilename] -> [InterpreterOutput s] -> Summary isSuccess :: Summarizable s => s -> Bool isFailure :: Summarizable s => s -> Bool isOther :: Summarizable s => s -> Bool -- | The entry point for mucheck module Test.MuCheck.Interpreter -- | Given the list of tests suites to check, run one test suite at a time -- on all mutants. mutantCheckSummary :: (Summarizable a, Show a) => ([String] -> [InterpreterOutput a] -> Summary) -> [String] -> String -> [String] -> FilePath -> IO () -- | Common functions used by MuCheck module Test.MuCheck.Utils.Common -- | The choose function generates subsets of a given size choose :: [a] -> Int -> [[a]] -- | The coupling function produces all possible pairings, and -- applies the given function to each coupling :: Eq a => (a -> a -> t) -> [a] -> [t] -- | The genFileNames function lazily generates filenames of mutants genFileNames :: String -> [String] -- | The replace function replaces first element in a list given old -- and new values as a pair replace :: Eq a => (a, a) -> [a] -> [a] -- | The sample function takes a random generator and chooses a -- random sample subset of given size. sample :: RandomGen g => g -> Int -> [t] -> [t] -- | The sampleF function takes a random generator, and a fraction -- and returns subset of size given by fraction sampleF :: RandomGen g => g -> Rational -> [t] -> [t] -- | The remElt function removes element at index specified from a -- list remElt :: Int -> [a] -> [a] -- | The swapElts function swaps two elements in a list given their -- indices swapElts :: Int -> Int -> [t] -> [t] -- | The genSwapped generates a list of lists where each element has -- been swapped by another genSwapped :: [t] -> [[t]] module Test.MuCheck.Operators -- | comparison operators [""", ""=", "/=", "=="] -- -- all available operators comparators :: [MuOp] -- | predicates ["pred", "id", "succ"] -- -- all available operators predNums :: [MuOp] -- | binary arithmetic ["+", "-", "*", "/"] -- -- all available operators binAriths :: [MuOp] -- | functions on lists ["sum", "product", "maximum", "minimum", "head", -- "last"] -- -- all available operators arithLists :: [MuOp] -- | all available operators allOps :: [MuOp] -- | Configuration module module Test.MuCheck.Config data GenerationMode FirstOrderOnly :: GenerationMode FirstAndHigherOrder :: GenerationMode -- | The configuration options if 1 is provided, all mutants are selected -- for that kind, and 0 ensures that no mutants are picked for that kind. -- Any fraction in between causes that many mutants to be picked randomly -- from the available pool data Config Config :: [MuOp] -> Rational -> Rational -> Rational -> Rational -> Int -> GenerationMode -> Config -- | Mutation operators on operator or function replacement muOps :: Config -> [MuOp] -- | Mutate pattern matches for functions? for example -- --
-- first [] = Nothing -- first (x:_) = Just x ---- -- is mutated to -- --
-- first (x:_) = Just x -- first [] = Nothing --doMutatePatternMatches :: Config -> Rational -- | Mutates integer values by +1 or -1 or by replacing it with 0 or 1 doMutateValues :: Config -> Rational -- | negate if conditions, that is -- --
-- if True then 1 else 0 ---- -- becomes -- --
-- if (not True) then 1 else 0 --doNegateIfElse :: Config -> Rational -- | negate guarded booleans in case statements, that is -- --
-- case v of -- True -> 1 -- otherwise -> 0 ---- -- becomes -- --
-- case v of -- (not True) -> 1 -- otherwise -> 0 --doNegateGuards :: Config -> Rational -- | Maximum number of mutants to generate. maxNumMutants :: Config -> Int -- | Generation mode, can be traditional (firstOrder) and higher order -- (higher order is experimental) genMode :: Config -> GenerationMode -- | The default configuration defaultConfig :: Config instance Eq GenerationMode instance Show GenerationMode instance Show Config -- | Mutation happens here. module Test.MuCheck.Mutation -- | The genMutants function is a wrapper to genMutantsWith with -- standard configuraton genMutants :: String -> FilePath -> IO Int -- | The genMutantsWith function takes configuration function to -- mutate, filename the function is defined in, and produces mutants in -- the same directory as the filename, and returns the number of mutants -- produced. genMutantsWith :: Config -> String -> FilePath -> IO Int -- | Mutating a function's code using a bunch of mutation operators (In all -- the three mutate functions, we assume working with functions -- declaration.) mutates :: [MuOp] -> Decl -> [Decl] mutatesN :: [MuOp] -> Decl -> Int -> [Decl] -- | Given a function, generate all mutants after applying applying op once -- (op might be applied at different places).E.g.: op = "== ">" -- and there are two instances of "<" mutate :: MuOp -> Decl -> [Decl] -- | is the parsed expression the function we are looking for? isFunctionD :: String -> Decl -> Bool -- | Generate all operators for permutating pattern matches in a function. -- We don't deal with permutating guards and case for now. permMatches :: Decl -> [MuOp] -- | generates transformations that removes one pattern match from a -- function definition. removeOnePMatch :: Decl -> [MuOp] -- | generate sub-arrays with one less element removeOneElem :: Eq t => [t] -> [[t]] -- | Parse a module. Input is the content of the file parseModuleFromFile :: String -> Module getDecls :: Module -> [Decl] putDecls :: Module -> [Decl] -> Module selectValOps :: (Data a, Eq a, Typeable b, Mutable b, Eq b) => (b -> Bool) -> [b -> b] -> a -> [MuOp] selectValOps' :: (Data a, Eq a, Typeable b, Mutable b) => (b -> Bool) -> (b -> [b]) -> a -> [MuOp] selectIntOps :: (Data a, Eq a) => a -> [MuOp] -- | negating boolean in if/else statements selectIfElseBoolNegOps :: (Data a, Eq a) => a -> [MuOp] -- | negating boolean in Guards selectGuardedBoolNegOps :: (Data a, Eq a) => a -> [MuOp] -- | MuCheck base module module Test.MuCheck -- | Perform mutation analysis mucheck :: (Summarizable a, Show a) => ([String] -> [InterpreterOutput a] -> Summary) -> String -> FilePath -> String -> [String] -> IO ()