packages feed

hpc-coveralls 0.2.2 → 0.3.0

raw patch · 8 files changed

+126/−72 lines, 8 filesdep +containersPVP ok

version bump matches the API change (PVP)

Dependencies added: containers

API changes (from Hackage documentation)

- Trace.Hpc.Coveralls.Config: testSuiteNames :: Config -> [String]
+ Trace.Hpc.Coveralls.Config: testSuites :: Config -> [String]
+ 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.Paths: hpcDir :: FilePath
+ Trace.Hpc.Paths: mixDir :: FilePath
+ Trace.Hpc.Paths: tixDir :: FilePath
- Trace.Hpc.Coveralls.Config: Config :: [String] -> [String] -> Config
+ Trace.Hpc.Coveralls.Config: Config :: [String] -> [FilePath] -> Config
- Trace.Hpc.Coveralls.Config: excludedDirs :: Config -> [String]
+ Trace.Hpc.Coveralls.Config: excludedDirs :: Config -> [FilePath]

Files

CHANGELOG.md view
@@ -1,4 +1,10 @@+[0.3.0](https://github.com/guillaume-nargeot/hpc-coveralls/issues?milestone=4&state=closed)+-----+* Support setting multiple test suites (issue #14)+* Process --exclude-dir value as a string prefix instead of a regex (issue #16)+ [0.2.2](https://github.com/guillaume-nargeot/hpc-coveralls/issues?milestone=3&state=closed)+----- * Prevent double compilation (issue #11) * Concurrently process cabal test stdout and stderr channels (issue #12) * Test with GHC 7.8.2
README.md view
@@ -1,4 +1,4 @@-hpc-coveralls [![Build Status](https://travis-ci.org/guillaume-nargeot/hpc-coveralls.png?branch=master)](https://travis-ci.org/guillaume-nargeot/hpc-coveralls)+hpc-coveralls [![Build Status](http://img.shields.io/travis/guillaume-nargeot/hpc-coveralls/master.svg)](https://travis-ci.org/guillaume-nargeot/hpc-coveralls) [![Gitter chat](http://img.shields.io/badge/gitter-chat--room-brightgreen.svg)](https://gitter.im/guillaume-nargeot/hpc-coveralls) [![BSD3 License](http://img.shields.io/badge/license-BSD3-brightgreen.svg)](https://tldrlegal.com/license/bsd-3-clause-license-%28revised%29) =============  hpc-coveralls converts and sends Haskell projects hpc code coverage to [coverall.io](http://coveralls.io/).@@ -18,7 +18,7 @@ script:   - cabal configure --enable-tests --enable-library-coverage && cabal build && cabal test after_script:-  - hpc-coveralls [options] [test-suite-name]+  - hpc-coveralls [options] [test-suite-names] ```  When using a GHC version prior to 7.8, you have to replace the `cabal test` command by `run-cabal-test`, as in the following example:@@ -29,7 +29,7 @@   - cabal configure --enable-tests --enable-library-coverage && cabal build   - run-cabal-test [options] [cabal-test-options] after_script:-  - hpc-coveralls [options] [test-suite-name]+  - hpc-coveralls [options] [test-suite-names] ```  The reason for this is explained in the next section.@@ -56,10 +56,12 @@  ## The hpc-coveralls command -At the moment, you can specify only one suite. For example, if your test suite is named `test-all`, use the command as follows:+This command parses the hpc generated output, converts its to Coveralls json format and finally sends it to coveralls.io over http.<br/>+Multiple test suites can be specified, in which case the coverage report will be made of the merged coverage data generated by the specified test suites.<br/>+For example, if your test suite are named `test1` and `test2`, use the command as follows:  ```yaml-hpc-coveralls test-all+hpc-coveralls test1 test2 ```  ### Options@@ -68,13 +70,13 @@ You can exclude source files located under the `test/` by using this option as in the following example:  ```yaml-hpc-coveralls --exclude-dir=test [test-suite-name]+hpc-coveralls --exclude-dir=test [test-suite-names] ```  You can specify multiple excluded folders by using the following example syntax:  ```yaml-hpc-coveralls --exclude-dir=test1 --exclude-dir=test2 [test-suite-name]+hpc-coveralls --exclude-dir=test1 --exclude-dir=test2 [test-suite-names] ```  # Limitations
hpc-coveralls.cabal view
@@ -1,5 +1,5 @@ name:           hpc-coveralls-version:        0.2.2+version:        0.3.0 synopsis:       Coveralls.io support for Haskell. description:   This utility converts and sends Haskell projects hpc code coverage to@@ -14,7 +14,7 @@   > script:   >   - cabal configure --enable-tests --enable-library-coverage && cabal build && cabal test   > after_script:-  >   - hpc-coveralls [options] [test-suite-name]+  >   - hpc-coveralls [options] [test-suite-names]   .   Further information can be found in the <https://github.com/guillaume-nargeot/hpc-coveralls README>. @@ -46,15 +46,17 @@     Trace.Hpc.Coveralls,     Trace.Hpc.Coveralls.Config,     Trace.Hpc.Coveralls.Curl,+    Trace.Hpc.Coveralls.Types,+    Trace.Hpc.Paths,     Trace.Hpc.Lix   build-depends:     aeson,     base < 5,     bytestring >= 0.10,+    containers >= 0.5,     cmdargs >= 0.10,     curl >= 1.3.8,-    hpc >= 0.6.0.0,-    regex-posix+    hpc >= 0.6.0.0  executable hpc-coveralls   hs-source-dirs: src@@ -63,10 +65,10 @@     aeson,     base < 5,     bytestring >= 0.10,+    containers >= 0.5,     cmdargs >= 0.10,     curl >= 1.3.8,-    hpc >= 0.6.0.0,-    regex-posix+    hpc >= 0.6.0.0   ghc-options:   -Wall -fwarn-tabs  executable run-cabal-test
src/HpcCoverallsMain.hs view
@@ -10,7 +10,7 @@ import System.Environment (getEnv, getEnvironment) import System.Exit (exitFailure, exitSuccess) import Trace.Hpc.Coveralls-import Trace.Hpc.Coveralls.Config+import Trace.Hpc.Coveralls.Config (Config(Config)) import Trace.Hpc.Coveralls.Curl  urlApiV1 :: String@@ -36,8 +36,8 @@  toConfig :: HpcCoverallsArgs -> Maybe Config toConfig hca = case testSuites hca of-    [testSuite] -> Just $ Config [testSuite] (excludeDirs hca)-    _           -> Nothing+    []             -> Nothing+    testSuiteNames -> Just $ Config testSuiteNames (excludeDirs hca)  main :: IO () main = do
src/Trace/Hpc/Coveralls.hs view
@@ -14,34 +14,15 @@ import Data.Aeson import Data.Aeson.Types () import Data.List+import qualified Data.Map.Strict as M import System.Exit (exitFailure)-import Text.Regex.Posix 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 -type CoverageData = (-    String,    -- source file path-    String,    -- file source code-    Mix,       -- module index data-    TixModule) -- tixs recorded by hpc---- 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--hpcDir :: String-hpcDir = "dist/hpc/"--tixDir :: String-tixDir = hpcDir ++ "tix/"--mixDir :: String-mixDir = hpcDir ++ "mix/"- lixToSimpleCoverage :: Lix -> SimpleCoverage lixToSimpleCoverage = map conv     where conv Full    = Number 2@@ -52,47 +33,67 @@ toSimpleCoverage :: Int -> [(MixEntry, Integer)] -> SimpleCoverage toSimpleCoverage lineCount = lixToSimpleCoverage . toLix lineCount -coverageToJson :: CoverageData -> Value-coverageToJson (filePath, source, mix, tix) = object [+coverageToJson :: FilePath -> ModuleCoverageData -> Value+coverageToJson filePath (source, mix, tixs) = object [     "name" .= filePath,     "source" .= source,     "coverage" .= coverage]     where coverage = toSimpleCoverage lineCount mixEntryTixs           lineCount = length $ lines source-          mixEntryTixs = zip (getMixEntries mix) (tixModuleTixs tix)+          mixEntryTixs = zip (getMixEntries mix) tixs           getMixEntries (Mix _ _ _ _ mixEntries) = mixEntries -toCoverallsJson :: String -> String -> [CoverageData] -> Value-toCoverallsJson serviceName jobId coverageData = object [+toCoverallsJson :: String -> String -> TestSuiteCoverageData -> Value+toCoverallsJson serviceName jobId testSuiteCoverageData = object [     "service_job_id" .= jobId,     "service_name" .= serviceName,-    "source_files" .= map coverageToJson coverageData]+    "source_files" .= toJsonCoverageList testSuiteCoverageData]+    where toJsonCoverageList = map (uncurry coverageToJson) . M.toList  matchAny :: [String] -> String -> Bool-matchAny patterns fileName = any (fileName =~) $ map ("^" ++) patterns+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++mergeModuleCoverageData :: ModuleCoverageData -> ModuleCoverageData -> ModuleCoverageData+mergeModuleCoverageData (source, mix, tixs1) (_, _, tixs2) =+    (source, mix, zipWith (+) tixs1 tixs2)++mergeCoverageData :: [TestSuiteCoverageData] -> TestSuiteCoverageData+mergeCoverageData = foldr1 (M.unionWith mergeModuleCoverageData)+ readMix' :: String -> TixModule -> IO Mix readMix' name tix = readMix [mixPath] (Right tix)-    where mixPath = mixDir ++ dirName ++ "/"-          dirName = case span (/= '/') modName of-              (_, []) -> name-              (packageId, _) -> packageId+    where mixPath = getMixPath name modName           TixModule modName _ _ _ = tix +getTixPath :: String -> IO FilePath+getTixPath testSuiteName = return $ tixDir ++ testSuiteName ++ "/" ++ getTixFileName testSuiteName+ -- | Create a list of coverage data from the tix input-toCoverageData :: String            -- ^ test suite name-               -> Tix               -- ^ tix data-               -> [String]          -- ^ excluded source folders-               -> IO [CoverageData] -- ^ coverage data list-toCoverageData testSuiteName (Tix tixs) excludeDirPatterns = do-    mixs <- mapM (readMix' testSuiteName) tixs-    let files = map filePath mixs-    sources <- mapM readFile files-    let coverageDataList = zip4 files sources mixs tixs-    return $ filter sourceDirFilter coverageDataList-    where filePath (Mix fp _ _ _ _) = fp-          sourceDirFilter = not . matchAny excludeDirPatterns . fst4-          fst4 (x, _, _, _) = x+readCoverageData :: String                   -- ^ test suite name+                 -> [String]                 -- ^ excluded source folders+                 -> IO TestSuiteCoverageData -- ^ coverage data list+readCoverageData testSuiteName excludeDirPatterns = do+    tixPath <- getTixPath testSuiteName+    mtix <- readTix tixPath+    case mtix of+        Nothing -> error ("Couldn't find the file " ++ tixPath) >> exitFailure+        Just (Tix tixs) -> do+            mixs <- mapM (readMix' testSuiteName) tixs+            let files = map filePath mixs+            sources <- mapM readFile files+            let coverageDataList = zip4 files sources mixs (map tixModuleTixs tixs)+            let filteredCoverageDataList = filter sourceDirFilter coverageDataList+            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@@ -100,11 +101,7 @@                          -> Config   -- ^ hpc-coveralls configuration                          -> IO Value -- ^ code coverage result in json format generateCoverallsFromTix serviceName jobId config = do-    mtix <- readTix tixPath-    case mtix of-        Nothing -> error ("Couldn't find the file " ++ tixPath) >> exitFailure-        Just tixs -> do-            coverageDatas <- toCoverageData testSuiteName tixs (excludedDirs config)-            return $ toCoverallsJson serviceName jobId coverageDatas-    where tixPath = tixDir ++ testSuiteName ++ "/" ++ getTixFileName testSuiteName-          testSuiteName = head (testSuiteNames config) -- multiple test suite mode is supported at the moment+    testSuitesCoverages <- mapM (`readCoverageData` excludedDirPatterns) testSuiteNames+    return $ toCoverallsJson serviceName jobId $ mergeCoverageData testSuitesCoverages+    where excludedDirPatterns = excludedDirs config+          testSuiteNames = testSuites config
src/Trace/Hpc/Coveralls/Config.hs view
@@ -1,6 +1,6 @@ module Trace.Hpc.Coveralls.Config where  data Config = Config {-    testSuiteNames :: [String],-    excludedDirs   :: [String]+    testSuites   :: [String],+    excludedDirs :: [FilePath]     }
+ src/Trace/Hpc/Coveralls/Types.hs view
@@ -0,0 +1,28 @@+-- |+-- Module:      Trace.Hpc.Coveralls.Types+-- Copyright:   (c) 2014 Guillaume Nargeot+-- License:     BSD3+-- Maintainer:  Guillaume Nargeot <guillaume+hackage@nargeot.com>+-- Stability:   experimental+--+-- Types to represent code coverage data hpc.++module Trace.Hpc.Coveralls.Types where++import Data.Aeson.Types (Value)+import qualified Data.Map as M+import Trace.Hpc.Mix++type ModuleCoverageData = (+    String,    -- file source code+    Mix,       -- module index data+    [Integer]) -- tixs recorded by hpc++type TestSuiteCoverageData = M.Map FilePath ModuleCoverageData++-- 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+
+ src/Trace/Hpc/Paths.hs view
@@ -0,0 +1,19 @@+-- |+-- 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/"