hpc-coveralls 0.3.0 → 0.4.0
raw patch · 15 files changed
+249/−164 lines, 15 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- HpcCoverallsCmdLine: CmdMain :: [String] -> [String] -> Bool -> HpcCoverallsArgs
- HpcCoverallsCmdLine: data HpcCoverallsArgs
- HpcCoverallsCmdLine: displayReport :: HpcCoverallsArgs -> Bool
- HpcCoverallsCmdLine: excludeDirs :: HpcCoverallsArgs -> [String]
- HpcCoverallsCmdLine: hpcCoverallsArgs :: HpcCoverallsArgs
- HpcCoverallsCmdLine: instance Data HpcCoverallsArgs
- HpcCoverallsCmdLine: instance Show HpcCoverallsArgs
- HpcCoverallsCmdLine: instance Typeable HpcCoverallsArgs
- HpcCoverallsCmdLine: testSuites :: HpcCoverallsArgs -> [String]
- Trace.Hpc.Coveralls.Config: Config :: [String] -> [FilePath] -> Config
- Trace.Hpc.Coveralls.Config: data Config
- Trace.Hpc.Coveralls.Config: excludedDirs :: Config -> [FilePath]
- Trace.Hpc.Coveralls.Config: testSuites :: Config -> [String]
- Trace.Hpc.Coveralls.Curl: PostFailure :: String -> PostResult
- Trace.Hpc.Coveralls.Curl: PostSuccess :: URLString -> PostResult
- Trace.Hpc.Coveralls.Curl: data PostResult
- Trace.Hpc.Coveralls.Curl: postJson :: String -> URLString -> IO PostResult
- Trace.Hpc.Coveralls.Types: type CoverageEntry = Value
- Trace.Hpc.Coveralls.Types: type ModuleCoverageData = (String, Mix, [Integer])
- Trace.Hpc.Coveralls.Types: type SimpleCoverage = [CoverageEntry]
- Trace.Hpc.Coveralls.Types: type TestSuiteCoverageData = Map FilePath ModuleCoverageData
- Trace.Hpc.Lix: Full :: Hit
- Trace.Hpc.Lix: Irrelevant :: Hit
- Trace.Hpc.Lix: None :: Hit
- Trace.Hpc.Lix: Partial :: Hit
- Trace.Hpc.Lix: data Hit
- Trace.Hpc.Lix: getLine :: MixEntry -> Int
- Trace.Hpc.Lix: groupByIndex :: Int -> [(Int, a)] -> [[a]]
- Trace.Hpc.Lix: instance Eq Hit
- Trace.Hpc.Lix: instance Show Hit
- Trace.Hpc.Lix: toHit :: [Bool] -> Hit
- Trace.Hpc.Lix: toLineHit :: (MixEntry, Integer) -> (Int, Bool)
- Trace.Hpc.Lix: toLix :: Int -> [(MixEntry, Integer)] -> Lix
- Trace.Hpc.Lix: type Lix = [Hit]
- Trace.Hpc.Paths: hpcDir :: FilePath
- Trace.Hpc.Paths: mixDir :: FilePath
- Trace.Hpc.Paths: tixDir :: FilePath
+ Trace.Hpc.Coveralls.Lix: getLine :: MixEntry -> Int
+ Trace.Hpc.Coveralls.Lix: toHit :: [Bool] -> Hit
+ Trace.Hpc.Coveralls.Lix: toLineHit :: (MixEntry, Integer) -> (Int, Bool)
+ Trace.Hpc.Coveralls.Lix: toLix :: Int -> [(MixEntry, Integer)] -> Lix
+ Trace.Hpc.Coveralls.Types: AllowPartialLines :: CoverageMode
+ Trace.Hpc.Coveralls.Types: Full :: Hit
+ Trace.Hpc.Coveralls.Types: Irrelevant :: Hit
+ Trace.Hpc.Coveralls.Types: None :: Hit
+ Trace.Hpc.Coveralls.Types: Partial :: Hit
+ Trace.Hpc.Coveralls.Types: PostFailure :: String -> PostResult
+ Trace.Hpc.Coveralls.Types: PostSuccess :: URLString -> PostResult
+ Trace.Hpc.Coveralls.Types: StrictlyFullLines :: CoverageMode
+ Trace.Hpc.Coveralls.Types: data CoverageMode
+ Trace.Hpc.Coveralls.Types: data Hit
+ Trace.Hpc.Coveralls.Types: data PostResult
+ Trace.Hpc.Coveralls.Types: instance Data CoverageMode
+ Trace.Hpc.Coveralls.Types: instance Default CoverageMode
+ Trace.Hpc.Coveralls.Types: instance Eq CoverageMode
+ Trace.Hpc.Coveralls.Types: instance Eq Hit
+ Trace.Hpc.Coveralls.Types: instance Show CoverageMode
+ Trace.Hpc.Coveralls.Types: instance Show Hit
+ Trace.Hpc.Coveralls.Types: instance Typeable CoverageMode
+ Trace.Hpc.Coveralls.Types: type Lix = [Hit]
+ Trace.Hpc.Coveralls.Util: fst4 :: (a, b, c, d) -> a
+ Trace.Hpc.Coveralls.Util: groupByIndex :: Int -> [(Int, a)] -> [[a]]
+ Trace.Hpc.Coveralls.Util: matchAny :: [String] -> String -> Bool
+ Trace.Hpc.Coveralls.Util: toFirstAndRest :: (a, b, c, d) -> (a, (b, c, d))
Files
- CHANGELOG.md +5/−0
- README.md +28/−6
- hpc-coveralls.cabal +9/−7
- src/HpcCoverallsCmdLine.hs +7/−2
- src/HpcCoverallsMain.hs +12/−10
- src/Trace/Hpc/Coveralls.hs +53/−43
- src/Trace/Hpc/Coveralls/Config.hs +5/−2
- src/Trace/Hpc/Coveralls/Curl.hs +5/−9
- src/Trace/Hpc/Coveralls/Lix.hs +42/−0
- src/Trace/Hpc/Coveralls/Paths.hs +31/−0
- src/Trace/Hpc/Coveralls/Types.hs +21/−13
- src/Trace/Hpc/Coveralls/Util.hs +28/−0
- src/Trace/Hpc/Lix.hs +0/−51
- src/Trace/Hpc/Paths.hs +0/−19
- test/TestAll.hs +3/−2
CHANGELOG.md view
@@ -1,3 +1,8 @@+[0.4.0](https://github.com/guillaume-nargeot/hpc-coveralls/issues?milestone=5&state=closed)+-----+* Add option to configure the coverage data conversion (issue #15)+* Add option to prevent from sending the coverage report (issue #17)+ [0.3.0](https://github.com/guillaume-nargeot/hpc-coveralls/issues?milestone=4&state=closed) ----- * Support setting multiple test suites (issue #14)
README.md view
@@ -41,8 +41,12 @@ When using hpc 0.6, `cabal test` outputs an error message and exits with the error code `1`, which results in a build failure. -In order to prevent this from happening, hpc-coveralls provides the `run-cabal-test` command which runs `cabal test` and returns with `0` if the regex `^Test suite .*: FAIL$` never matches any line of the output.+In order to prevent this from happening, hpc-coveralls provides the `run-cabal-test` command which runs `cabal test` and returns with `0` if the following regex never matches any line of the output: +```perl+/^Test suite .*: FAIL$/+```+ As this issue is fixed in the hpc version shipped with GHC 7.8, you don't have to use `run-cabal-test` when testing with GHC 7.8 and can safely use `cabal test`. ### Options@@ -66,7 +70,9 @@ ### Options -The `--exclude-dir` option can be used to exclude source files located under a given directory from the coverage report.<br/>+#### --exclude-dir++The `--exclude-dir` option allows to exclude source files located under a given directory from the coverage report.<br/> You can exclude source files located under the `test/` by using this option as in the following example: ```yaml@@ -79,22 +85,38 @@ hpc-coveralls --exclude-dir=test1 --exclude-dir=test2 [test-suite-names] ``` -# Limitations+#### --coverage-mode -As Coveralls doesn't support yet partial-line coverage, the following convention is used to represent line coverage with line hit counts:+As Coveralls doesn't support partial-line coverage yet, hpc-coveralls currently converts hpc coverage data into line based coverage data, which is the only format supported at the moment.+The `--coverage-mode` option allows to configure how the coverage data is converted into Coveralls format, based on your needs.<br/>+Below are the two modes currently available, with an explanation of what the hit count values mean.++`--coverage-mode=AllowPartialLines` (default): - `0` : the line is never hit, - `1` : the line is partially covered, - `2` : the line is fully covered. -This convention is the same as the one used by [cloverage](https://github.com/lshift/cloverage) coveralls output for Clojure projects code coverage.+Note that `AllowPartialLines` conversion mode follows the same convention as the one used by [cloverage](https://github.com/lshift/cloverage) coveralls output for Clojure projects code coverage. -There's an [open issue](https://github.com/lemurheavy/coveralls-public/issues/216) to improve this.+`--coverage-mode=StrictlyFullLines`:+- `0` : the line is never hit or only partially covered,+- `1` : the line is fully covered. +Please also note that there is an [open issue](https://github.com/lemurheavy/coveralls-public/issues/216) on coveralls issue tracker in order to improve this (add support for partial line coverage).++#### --dont-send++The `--dont-send` option prevents hpc-coveralls from sending the coverage report to coveralls.io.+This option can be used together with `--display-report` for testing purpose.<br/>+For example, you can try various combinations of the other options and confirm the difference in the resulting report outputs.+ # Contributing hpc-coveralls is still under development and any contributions are welcome! [Future Plans and Ideas](https://github.com/guillaume-nargeot/hpc-coveralls/wiki/Future-Plans-and-Ideas)++Please share your comments and suggestions on hpc-coveralls [Gitter channel](https://gitter.im/guillaume-nargeot/hpc-coveralls)! # License
hpc-coveralls.cabal view
@@ -1,5 +1,5 @@ name: hpc-coveralls-version: 0.3.0+version: 0.4.0 synopsis: Coveralls.io support for Haskell. description: This utility converts and sends Haskell projects hpc code coverage to@@ -42,13 +42,15 @@ library hs-source-dirs: src exposed-modules:- HpcCoverallsCmdLine, Trace.Hpc.Coveralls,+ Trace.Hpc.Coveralls.Lix,+ Trace.Hpc.Coveralls.Types,+ Trace.Hpc.Coveralls.Util+ other-modules:+ HpcCoverallsCmdLine, Trace.Hpc.Coveralls.Config, Trace.Hpc.Coveralls.Curl,- Trace.Hpc.Coveralls.Types,- Trace.Hpc.Paths,- Trace.Hpc.Lix+ Trace.Hpc.Coveralls.Paths build-depends: aeson, base < 5,@@ -69,7 +71,7 @@ cmdargs >= 0.10, curl >= 1.3.8, hpc >= 0.6.0.0- ghc-options: -Wall -fwarn-tabs+ ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns executable run-cabal-test hs-source-dirs: src@@ -80,7 +82,7 @@ process, regex-posix, split- ghc-options: -Wall -fwarn-tabs+ ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns test-suite test-all hs-source-dirs: test
src/HpcCoverallsCmdLine.hs view
@@ -6,17 +6,22 @@ import Data.Version (Version(..)) import Paths_hpc_coveralls (version) import System.Console.CmdArgs+import Trace.Hpc.Coveralls.Types data HpcCoverallsArgs = CmdMain { excludeDirs :: [String] , testSuites :: [String] , displayReport :: Bool+ , dontSend :: Bool+ , coverageMode :: CoverageMode } deriving (Data, Show, Typeable) hpcCoverallsArgs :: HpcCoverallsArgs hpcCoverallsArgs = CmdMain- { excludeDirs = [] &= explicit &= typDir &= name "exclude-dir" &= help "Exclude sources files under the matching directory from the coverage report send to coveralls.io"- , displayReport = False &= explicit &= name "display-report" &= help "Display the json code coverage report that will be sent to coveralls.io"+ { excludeDirs = [] &= explicit &= typDir &= name "exclude-dir" &= help "Exclude sources files under the matching directory from the coverage report"+ , displayReport = False &= explicit &= name "display-report" &= help "Display the json code coverage report that will be sent to coveralls.io"+ , dontSend = False &= explicit &= name "dont-send" &= help "Do not send the report to coveralls.io"+ , coverageMode = AllowPartialLines &= explicit &= typ "MODE" &= name "coverage-mode" &= help "Coverage conversion mode: AllowPartialLines (default), StrictlyFullLines" , testSuites = [] &= typ "TEST-SUITE" &= args } &= summary ("hpc-coveralls-" ++ versionString version ++ ", (C) Guillaume Nargeot 2014") &= program "hpc-coveralls"
src/HpcCoverallsMain.hs view
@@ -1,5 +1,6 @@ module Main where +import Control.Applicative import Control.Monad import Data.Aeson import qualified Data.ByteString.Lazy.Char8 as BSL@@ -19,7 +20,7 @@ getServiceAndJobID :: IO (String, String) getServiceAndJobID = do env <- getEnvironment- case fmap snd $ find (isJust . flip lookup env . fst) ciEnvVars of+ case snd <$> find (isJust . flip lookup env . fst) ciEnvVars of Just (ciName, jobIdVarName) -> do jobId <- getEnv jobIdVarName return (ciName, jobId)@@ -34,23 +35,24 @@ writeJson :: String -> Value -> IO () writeJson filePath = BSL.writeFile filePath . encode -toConfig :: HpcCoverallsArgs -> Maybe Config-toConfig hca = case testSuites hca of+getConfig :: HpcCoverallsArgs -> Maybe Config+getConfig hca = case testSuites hca of [] -> Nothing- testSuiteNames -> Just $ Config testSuiteNames (excludeDirs hca)+ testSuiteNames -> Just $ Config testSuiteNames (excludeDirs hca) (coverageMode hca) main :: IO () main = do hca <- cmdArgs hpcCoverallsArgs- case toConfig hca of+ case getConfig hca of Nothing -> putStrLn "Please specify a target test suite name" >> exitSuccess Just config -> do (serviceName, jobId) <- getServiceAndJobID coverallsJson <- generateCoverallsFromTix serviceName jobId config- let filePath = serviceName ++ "-" ++ jobId ++ ".json" when (displayReport hca) $ BSL.putStrLn $ encode coverallsJson+ let filePath = serviceName ++ "-" ++ jobId ++ ".json" writeJson filePath coverallsJson- response <- postJson filePath urlApiV1- case response of- PostSuccess url -> putStrLn ("URL: " ++ url) >> exitSuccess- PostFailure msg -> putStrLn ("Error: " ++ msg) >> exitFailure+ unless (dontSend hca) $ do+ response <- postJson filePath urlApiV1+ case response of+ PostSuccess url -> putStrLn ("URL: " ++ url) >> exitSuccess+ PostFailure msg -> putStrLn ("Error: " ++ msg) >> exitFailure
src/Trace/Hpc/Coveralls.hs view
@@ -7,57 +7,71 @@ -- Maintainer: Guillaume Nargeot <guillaume+hackage@nargeot.com> -- Stability: experimental ----- Types and functions for converting and sending hpc output to coveralls.io.+-- Functions for converting and sending hpc output to coveralls.io. module Trace.Hpc.Coveralls ( generateCoverallsFromTix ) where -import Data.Aeson-import Data.Aeson.Types ()-import Data.List+import Data.Aeson+import Data.Aeson.Types ()+import Data.List import qualified Data.Map.Strict as M-import System.Exit (exitFailure)-import Trace.Hpc.Coveralls.Config-import Trace.Hpc.Coveralls.Types-import Trace.Hpc.Lix-import Trace.Hpc.Mix-import Trace.Hpc.Paths-import Trace.Hpc.Tix+import System.Exit (exitFailure)+import Trace.Hpc.Coveralls.Config+import Trace.Hpc.Coveralls.Lix+import Trace.Hpc.Coveralls.Paths+import Trace.Hpc.Coveralls.Types+import Trace.Hpc.Coveralls.Util+import Trace.Hpc.Mix+import Trace.Hpc.Tix -lixToSimpleCoverage :: Lix -> SimpleCoverage-lixToSimpleCoverage = map conv- where conv Full = Number 2- conv Partial = Number 1- conv None = Number 0- conv Irrelevant = Null+type ModuleCoverageData = (+ String, -- file source code+ Mix, -- module index data+ [Integer]) -- tixs recorded by hpc -toSimpleCoverage :: Int -> [(MixEntry, Integer)] -> SimpleCoverage-toSimpleCoverage lineCount = lixToSimpleCoverage . toLix lineCount+type TestSuiteCoverageData = M.Map FilePath ModuleCoverageData -coverageToJson :: FilePath -> ModuleCoverageData -> Value-coverageToJson filePath (source, mix, tixs) = object [+-- single file coverage data in the format defined by coveralls.io+type SimpleCoverage = [CoverageEntry]++-- Is there a way to restrict this to only Number and Null?+type CoverageEntry = Value++type LixConverter = Lix -> SimpleCoverage++strictConverter :: LixConverter+strictConverter = map $ \lix -> case lix of+ Full -> Number 1+ Partial -> Number 0+ None -> Number 0+ Irrelevant -> Null++looseConverter :: LixConverter+looseConverter = map $ \lix -> case lix of+ Full -> Number 2+ Partial -> Number 1+ None -> Number 0+ Irrelevant -> Null++toSimpleCoverage :: LixConverter -> Int -> [(MixEntry, Integer)] -> SimpleCoverage+toSimpleCoverage convert lineCount = convert . toLix lineCount++coverageToJson :: LixConverter -> FilePath -> ModuleCoverageData -> Value+coverageToJson converter filePath (source, mix, tixs) = object [ "name" .= filePath, "source" .= source, "coverage" .= coverage]- where coverage = toSimpleCoverage lineCount mixEntryTixs+ where coverage = toSimpleCoverage converter lineCount mixEntryTixs lineCount = length $ lines source mixEntryTixs = zip (getMixEntries mix) tixs getMixEntries (Mix _ _ _ _ mixEntries) = mixEntries -toCoverallsJson :: String -> String -> TestSuiteCoverageData -> Value-toCoverallsJson serviceName jobId testSuiteCoverageData = object [+toCoverallsJson :: String -> String -> LixConverter -> TestSuiteCoverageData -> Value+toCoverallsJson serviceName jobId converter testSuiteCoverageData = object [ "service_job_id" .= jobId, "service_name" .= serviceName, "source_files" .= toJsonCoverageList testSuiteCoverageData]- where toJsonCoverageList = map (uncurry coverageToJson) . M.toList--matchAny :: [String] -> String -> Bool-matchAny patterns fileName = any (`isPrefixOf` fileName) patterns--getMixPath :: String -> String -> FilePath-getMixPath testSuiteName modName = mixDir ++ dirName ++ "/"- where dirName = case span (/= '/') modName of- (_, []) -> testSuiteName- (packageId, _) -> packageId+ where toJsonCoverageList = map (uncurry $ coverageToJson converter) . M.toList mergeModuleCoverageData :: ModuleCoverageData -> ModuleCoverageData -> ModuleCoverageData mergeModuleCoverageData (source, mix, tixs1) (_, _, tixs2) =@@ -67,12 +81,7 @@ mergeCoverageData = foldr1 (M.unionWith mergeModuleCoverageData) readMix' :: String -> TixModule -> IO Mix-readMix' name tix = readMix [mixPath] (Right tix)- where mixPath = getMixPath name modName- TixModule modName _ _ _ = tix--getTixPath :: String -> IO FilePath-getTixPath testSuiteName = return $ tixDir ++ testSuiteName ++ "/" ++ getTixFileName testSuiteName+readMix' name tix = readMix [getMixPath name tix] (Right tix) -- | Create a list of coverage data from the tix input readCoverageData :: String -- ^ test suite name@@ -92,8 +101,6 @@ return $ M.fromList $ map toFirstAndRest filteredCoverageDataList where filePath (Mix fp _ _ _ _) = fp sourceDirFilter = not . matchAny excludeDirPatterns . fst4- fst4 (x, _, _, _) = x- toFirstAndRest (a, b, c, d) = (a, (b, c, d)) -- | Generate coveralls json formatted code coverage from hpc coverage data generateCoverallsFromTix :: String -- ^ CI name@@ -102,6 +109,9 @@ -> IO Value -- ^ code coverage result in json format generateCoverallsFromTix serviceName jobId config = do testSuitesCoverages <- mapM (`readCoverageData` excludedDirPatterns) testSuiteNames- return $ toCoverallsJson serviceName jobId $ mergeCoverageData testSuitesCoverages+ return $ toCoverallsJson serviceName jobId converter $ mergeCoverageData testSuitesCoverages where excludedDirPatterns = excludedDirs config testSuiteNames = testSuites config+ converter = case coverageMode config of+ StrictlyFullLines -> strictConverter+ AllowPartialLines -> looseConverter
src/Trace/Hpc/Coveralls/Config.hs view
@@ -1,6 +1,9 @@ module Trace.Hpc.Coveralls.Config where +import Trace.Hpc.Coveralls.Types (CoverageMode)+ data Config = Config {- testSuites :: [String],- excludedDirs :: [FilePath]+ testSuites :: ![String],+ excludedDirs :: ![FilePath],+ coverageMode :: !CoverageMode }
src/Trace/Hpc/Coveralls/Curl.hs view
@@ -12,16 +12,12 @@ module Trace.Hpc.Coveralls.Curl ( postJson, PostResult (..) ) where -import Data.Aeson-import Data.Aeson.Types (parseMaybe)+import Data.Aeson+import Data.Aeson.Types (parseMaybe) import qualified Data.ByteString.Lazy.Char8 as LBS-import Data.Maybe-import Network.Curl---- | Result to the POST request to coveralls.io-data PostResult =- PostSuccess URLString -- ^ Coveralls job url- | PostFailure String -- ^ error message+import Data.Maybe+import Network.Curl+import Trace.Hpc.Coveralls.Types parseResponse :: CurlResponse -> PostResult parseResponse r = case respCurlCode r of
+ src/Trace/Hpc/Coveralls/Lix.hs view
@@ -0,0 +1,42 @@+-- |+-- Module: Trace.Hpc.Coveralls.Lix+-- Copyright: (c) 2014 Guillaume Nargeot+-- License: BSD3+-- Maintainer: Guillaume Nargeot <guillaume+hackage@nargeot.com>+-- Stability: experimental+-- Portability: portable+--+-- Functions for converting hpc output to line-based code coverage data.++module Trace.Hpc.Coveralls.Lix where++import Data.List+import Data.Ord+import Prelude hiding (getLine)+import Trace.Hpc.Coveralls.Types+import Trace.Hpc.Coveralls.Util+import Trace.Hpc.Mix+import Trace.Hpc.Util++toHit :: [Bool] -> Hit+toHit [] = Irrelevant+toHit [x] = if x then Full else None+toHit xs+ | and xs = Full+ | or xs = Partial+ | otherwise = None++getLine :: MixEntry -> Int+getLine = fffst . fromHpcPos . fst+ where fffst (x, _, _, _) = x++toLineHit :: (MixEntry, Integer) -> (Int, Bool)+toLineHit (entry, cnt) = (getLine entry - 1, cnt > 0)++-- | Convert hpc coverage entries into a line based coverage format+toLix :: Int -- ^ Source line count+ -> [(MixEntry, Integer)] -- ^ Mix entries and associated hit count+ -> Lix -- ^ Line coverage+toLix lineCount entries = map toHit (groupByIndex lineCount sortedLineHits)+ where sortedLineHits = sortBy (comparing fst) lineHits+ lineHits = map toLineHit entries
+ src/Trace/Hpc/Coveralls/Paths.hs view
@@ -0,0 +1,31 @@+-- |+-- Module: Trace.Hpc.Coveralls.Paths+-- Copyright: (c) 2014 Guillaume Nargeot+-- License: BSD3+-- Maintainer: Guillaume Nargeot <guillaume+hackage@nargeot.com>+-- Stability: experimental+--+-- Paths constants and functions for hpc coverage report output.++module Trace.Hpc.Coveralls.Paths where++import Trace.Hpc.Tix++hpcDir :: FilePath+hpcDir = "dist/hpc/"++tixDir :: FilePath+tixDir = hpcDir ++ "tix/"++mixDir :: FilePath+mixDir = hpcDir ++ "mix/"++getMixPath :: String -> TixModule -> FilePath+getMixPath testSuiteName tix = mixDir ++ dirName ++ "/"+ where dirName = case span (/= '/') modName of+ (_, []) -> testSuiteName+ (packageId, _) -> packageId+ TixModule modName _ _ _ = tix++getTixPath :: String -> IO FilePath+getTixPath testSuiteName = return $ tixDir ++ testSuiteName ++ "/" ++ getTixFileName testSuiteName
src/Trace/Hpc/Coveralls/Types.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE DeriveDataTypeable #-}+ -- | -- Module: Trace.Hpc.Coveralls.Types -- Copyright: (c) 2014 Guillaume Nargeot@@ -5,24 +7,30 @@ -- Maintainer: Guillaume Nargeot <guillaume+hackage@nargeot.com> -- Stability: experimental ----- Types to represent code coverage data hpc.+-- Types to represent hpc code coverage data. module Trace.Hpc.Coveralls.Types where -import Data.Aeson.Types (Value)-import qualified Data.Map as M-import Trace.Hpc.Mix+import Data.Data+import Network.Curl+import System.Console.CmdArgs.Default -type ModuleCoverageData = (- String, -- file source code- Mix, -- module index data- [Integer]) -- tixs recorded by hpc+data Hit = Full+ | Partial+ | None+ | Irrelevant+ deriving (Eq, Show) -type TestSuiteCoverageData = M.Map FilePath ModuleCoverageData+type Lix = [Hit] --- single file coverage data in the format defined by coveralls.io-type SimpleCoverage = [CoverageEntry]+instance Default CoverageMode where+ def = AllowPartialLines --- Is there a way to restrict this to only Number and Null?-type CoverageEntry = Value+data CoverageMode = StrictlyFullLines+ | AllowPartialLines+ deriving (Data, Eq, Show, Typeable) +-- | Result to the POST request to coveralls.io+data PostResult =+ PostSuccess URLString -- ^ Coveralls job url+ | PostFailure String -- ^ error message
+ src/Trace/Hpc/Coveralls/Util.hs view
@@ -0,0 +1,28 @@+-- |+-- Module: Trace.Hpc.Coveralls.Util+-- Copyright: (c) 2014 Guillaume Nargeot+-- License: BSD3+-- Maintainer: Guillaume Nargeot <guillaume+hackage@nargeot.com>+-- Stability: experimental+--+-- Utility functions.++module Trace.Hpc.Coveralls.Util where++import Data.List++fst4 :: (a, b, c, d) -> a+fst4 (x, _, _, _) = x++toFirstAndRest :: (a, b, c, d) -> (a, (b, c, d))+toFirstAndRest (a, b, c, d) = (a, (b, c, d))++matchAny :: [String] -> String -> Bool+matchAny patterns fileName = any (`isPrefixOf` fileName) patterns++groupByIndex :: Int -> [(Int, a)] -> [[a]]+groupByIndex size = take size . flip (++) (repeat []) . groupByIndex' 0 []+ where groupByIndex' _ ys [] = [ys]+ groupByIndex' i ys xx@((xi, x) : xs) = if xi == i+ then groupByIndex' i (x : ys) xs+ else ys : groupByIndex' (i + 1) [] xx
− src/Trace/Hpc/Lix.hs
@@ -1,51 +0,0 @@--- |--- Module: Trace.Hpc.Lix--- Copyright: (c) 2014 Guillaume Nargeot--- License: BSD3--- Maintainer: Guillaume Nargeot <guillaume+hackage@nargeot.com>--- Stability: experimental--- Portability: portable------ Types and functions for converting hpc output to line-based code coverage data.--module Trace.Hpc.Lix where--import Data.List-import Data.Ord-import Prelude hiding (getLine)-import Trace.Hpc.Mix-import Trace.Hpc.Util--data Hit = Full | Partial | None | Irrelevant deriving (Eq, Show)--type Lix = [Hit]--groupByIndex :: Int -> [(Int, a)] -> [[a]]-groupByIndex size = take size . flip (++) (repeat []) . groupByIndex' 0 []- where groupByIndex' _ ys [] = [ys]- groupByIndex' i ys xx@((xi, x) : xs) = if xi == i- then groupByIndex' i (x : ys) xs- else ys : groupByIndex' (i + 1) [] xx--toHit :: [Bool] -> Hit-toHit [] = Irrelevant-toHit [x] = if x then Full else None-toHit xs- | and xs = Full- | or xs = Partial- | otherwise = None--getLine :: MixEntry -> Int-getLine = fffst . fromHpcPos . fst- where fffst (x, _, _, _) = x--toLineHit :: (MixEntry, Integer) -> (Int, Bool)-toLineHit (entry, cnt) = (getLine entry - 1, cnt > 0)---- | Convert hpc coverage entries into a line based coverage format-toLix :: Int -- ^ Source line count- -> [(MixEntry, Integer)] -- ^ Mix entries and associated hit count- -> Lix -- ^ Line coverage-toLix lineCount entries = map toHit (groupByIndex lineCount sortedLineHits)- where sortedLineHits = sortBy (comparing fst) lineHits- lineHits = map toLineHit entries
− src/Trace/Hpc/Paths.hs
@@ -1,19 +0,0 @@--- |--- Module: Trace.Hpc.Paths--- Copyright: (c) 2014 Guillaume Nargeot--- License: BSD3--- Maintainer: Guillaume Nargeot <guillaume+hackage@nargeot.com>--- Stability: experimental------ Paths constants for hpc coverage report output.--module Trace.Hpc.Paths where--hpcDir :: FilePath-hpcDir = "dist/hpc/"--tixDir :: FilePath-tixDir = hpcDir ++ "tix/"--mixDir :: FilePath-mixDir = hpcDir ++ "mix/"
test/TestAll.hs view
@@ -2,10 +2,11 @@ import System.Exit ( exitFailure, exitSuccess ) import Test.HUnit-import TestHpcLix+import TestHpcCoverallsLix+import TestHpcCoverallsUtil allTests :: [Test]-allTests = [testHpcLix]+allTests = [testLix, testUtil] main :: IO Counts main = do