packages feed

hpc-lcov-1.0.0: test/Lcov.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}

module Lcov where

import Data.List (sortOn)
import Test.Tasty (TestTree)
import Test.Tasty.HUnit (testCase, (@?=))
import Trace.Hpc.Mix (BoxLabel(..), CondBox(..))
import Trace.Hpc.Tix (TixModule(..))
import Trace.Hpc.Util (Hash, HpcPos, toHash, toHpcPos)

import Trace.Hpc.Lcov
import Trace.Hpc.Lcov.Report

test_generate_lcov_top_level :: TestTree
test_generate_lcov_top_level = testCase "generateLcovFromTix FunctionReport TopLevelBox" $
    let report = generateLcovFromTixMix
          [ TixMix "Test" "Test.hs"
              [ TixMixEntry 1 (TopLevelBox ["foo"]) 0
              , TixMixEntry 2 (TopLevelBox ["bar"]) 10
              ]
          ]
    in fromReport report @?=
      [ FileReport "Test.hs"
          [ FunctionReport 1 "foo" 0
          , FunctionReport 2 "bar" 10
          ]
          []
          []
      ]

test_generate_lcov_local :: TestTree
test_generate_lcov_local = testCase "generateLcovFromTix FunctionReport LocalBox" $
    let report = generateLcovFromTixMix
          [ TixMix "Test" "Test.hs"
              [ TixMixEntry 1 (LocalBox ["foo", "bar"]) 0
              , TixMixEntry 2 (LocalBox ["foo", "baz"]) 10
              ]
          ]
    in fromReport report @?=
      [ FileReport "Test.hs"
          [ FunctionReport 1 "foo$bar" 0
          , FunctionReport 2 "foo$baz" 10
          ]
          []
          []
      ]

test_generate_lcov_branch :: TestTree
test_generate_lcov_branch = testCase "generateLcovFromTix BranchReport" $
    let report = generateLcovFromTixMix
          [ TixMix "Test" "Test.hs"
              [ TixMixEntry 1 (BinBox GuardBinBox True) 0
              , TixMixEntry 1 (BinBox GuardBinBox False) 10
              ]
          ]
    in fromReport report @?=
      [ FileReport "Test.hs"
          []
          [ BranchReport 1 (getHash 1) 0 10
          ]
          []
      ]

test_generate_lcov_line :: TestTree
test_generate_lcov_line = testCase "generateLcovFromTix LineReport" $
    let report = generateLcovFromTixMix
          [ TixMix "Test" "Test.hs"
              [ TixMixEntry 1 (ExpBox True) 0
              , TixMixEntry 2 (ExpBox False) 10
              , TixMixEntry 2 (ExpBox True) 4
              , TixMixEntry 3 (ExpBox False) 0
              , TixMixEntry 3 (ExpBox True) 2
              ]
          ]
    in fromReport report @?=
      [ FileReport "Test.hs"
          []
          []
          [ LineReport 1 0
          -- these take the highest hit count for the line
          , LineReport 2 10
          , LineReport 3 2
          ]
      ]

test_generate_lcov_merge_tixs :: TestTree
test_generate_lcov_merge_tixs = testCase "generateLcovFromTix merge .tix files" $
  let report = generateLcovFromTix
        [ mkModuleToMix "Test" "Test.hs"
            [ (1, TopLevelBox ["foo"])
            , (2, LocalBox ["foo", "bar"])
            , (3, ExpBox True)
            , (3, BinBox CondBinBox True)
            , (3, BinBox CondBinBox False)
            ]
        ]
        [ mkTix "Test" [1, 2, 3, 4, 0]
        , mkTix "Test" [2, 3, 4, 5, 0]
        ]
  in fromReport report @?=
    [ FileReport "Test.hs"
        [ FunctionReport 1 "foo" 3
        , FunctionReport 2 "foo$bar" 5
        ]
        [ BranchReport 3 (getHash 3) 9 0
        ]
        [ LineReport 3 7
        ]
    ]

{- Helpers -}

mkTix :: String -> [Integer] -> TixModule
mkTix moduleName ticks = TixModule moduleName 0 (length ticks) ticks

mkModuleToMix :: String -> FilePath -> [(Int, BoxLabel)] -> (String, FileInfo)
mkModuleToMix moduleName filePath mixEntries = (moduleName, (filePath, mixs))
  where
    mixs = flip map mixEntries $ \(line, boxLabel) -> (getHpcPos line, boxLabel)

data TixMix = TixMix
  { tixMixModule   :: String
  , tixMixFilePath :: FilePath
  , tixMixEntries  :: [TixMixEntry]
  }

data TixMixEntry = TixMixEntry
  { tixMixEntryLine  :: Int
  , tixMixBoxLabel   :: BoxLabel
  , tixMixEntryTicks :: Integer
  }

generateLcovFromTixMix :: [TixMix] -> LcovReport
generateLcovFromTixMix = uncurry generateLcovFromTix . unzip . map fromTixMix
  where
    fromTixMix TixMix{..} =
      let toMixEntry (TixMixEntry line boxLabel _) = (line, boxLabel)
          moduleToMix = mkModuleToMix tixMixModule tixMixFilePath $ map toMixEntry tixMixEntries
          tix = mkTix tixMixModule $ map tixMixEntryTicks tixMixEntries
      in (moduleToMix, tix)

fromReport :: LcovReport -> [FileReport]
fromReport (LcovReport fileReports) = sortOn fileReportLocation fileReports

getHpcPos :: Int -> HpcPos
getHpcPos line = toHpcPos (line, 0, 0, 0)

getHash :: Int -> Hash
getHash = toHash . getHpcPos