From 0c37de7a9d2f3bbda720379bdd3110fc281fe874 Mon Sep 17 00:00:00 2001 From: Thomas Tuegel Date: Wed, 22 Nov 2017 10:59:46 -0600 Subject: [PATCH 1/2] cabal-testsuite: test cabal new-test with coverage --- .../ExeV10/cabal-with-hpc.multitest.hs | 51 ++++++++++ .../ExeV10/setup-with-hpc.multitest.hs | 98 ------------------- .../TestSuiteTests/ExeV10/setup-with-hpc.out | 0 .../TestSuiteTests/ExeV10/setup.out | 18 ---- .../TestSuiteTests/ExeV10/setup.test.hs | 7 -- 5 files changed, 51 insertions(+), 123 deletions(-) create mode 100644 cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/cabal-with-hpc.multitest.hs delete mode 100644 cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup-with-hpc.multitest.hs delete mode 100644 cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup-with-hpc.out delete mode 100644 cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup.out delete mode 100644 cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup.test.hs diff --git a/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/cabal-with-hpc.multitest.hs b/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/cabal-with-hpc.multitest.hs new file mode 100644 index 00000000000..08576949700 --- /dev/null +++ b/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/cabal-with-hpc.multitest.hs @@ -0,0 +1,51 @@ +import qualified Control.Exception as E (IOException, catch) +import Control.Monad (unless) +import Control.Monad.IO.Class (liftIO) +import Data.Maybe (catMaybes) + +import qualified Distribution.Verbosity as Verbosity + +import Test.Cabal.Prelude + +main = + forM_ (choose4 [True, False]) $ \(libProf, exeProf, exeDyn, shared) -> + do + let + opts = catMaybes + [ enable libProf "library-profiling" + , enable exeProf "profiling" + , enable exeDyn "executable-dynamic" + , enable shared "shared" + ] + where + enable cond flag + | cond = Just $ "--enable-" ++ flag + | otherwise = Nothing + args = "test-Short" : "--enable-coverage" : opts + cabalTest . recordMode DoNotRecord $ do + hasShared <- hasSharedLibraries + hasProfiled <- hasProfiledLibraries + hpcOk <- liftIO $ correctHpcVersion + let + skip = + not hpcOk + || (not hasShared && (exeDyn || shared)) + || (not hasProfiled && (libProf || exeProf)) + unless skip $ cabal "new-test" args + where + choose4 :: [a] -> [(a, a, a, a)] + choose4 xs = liftM4 (,,,) xs xs xs xs + +-- | Checks for a suitable HPC version for testing. +correctHpcVersion :: IO Bool +correctHpcVersion = do + let programDb' = emptyProgramDb + let verbosity = Verbosity.normal + let verRange = orLaterVersion (mkVersion [0,7]) + programDb <- configureProgram verbosity hpcProgram programDb' + (requireProgramVersion verbosity hpcProgram verRange programDb + >> return True) `catchIO` (\_ -> return False) + where + -- Distribution.Compat.Exception is hidden. + catchIO :: IO a -> (E.IOException -> IO a) -> IO a + catchIO = E.catch diff --git a/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup-with-hpc.multitest.hs b/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup-with-hpc.multitest.hs deleted file mode 100644 index 8d5e5db291a..00000000000 --- a/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup-with-hpc.multitest.hs +++ /dev/null @@ -1,98 +0,0 @@ -import qualified Control.Exception as E (IOException, catch) -import Control.Monad -import Control.Monad.IO.Class -import Data.Maybe (catMaybes) -import System.FilePath -import Data.List - -import Distribution.Compiler (CompilerFlavor(..), CompilerId(..)) -import Distribution.Simple.Compiler (compilerId) -import Distribution.Types.LocalBuildInfo (localPackage) -import Distribution.Simple.LocalBuildInfo (compiler, localCompatPackageKey) -import Distribution.Simple.Hpc -import Distribution.Simple.Program.Builtin (hpcProgram) -import Distribution.Simple.Program.Db - ( emptyProgramDb, configureProgram, requireProgramVersion ) -import Distribution.Text (display) -import qualified Distribution.Verbosity as Verbosity -import Distribution.Version (mkVersion, orLaterVersion) - -import Test.Cabal.Prelude - -main = - forM_ (choose4 [True, False]) $ \(libProf, exeProf, exeDyn, shared) -> - -- NB: inside so we cleanup each time. This seems to - -- be important on Mac OS X, where leftover build products - -- can cause errors like this: - -- - -- Test suite test-Short: RUNNING... - -- setup-with-hpc.dist/dist/build/test-Short/test-Short - -- dyld: Library not loaded: - -- @rpath/libHSmy-0.1-B1rF0UIcOou1OUvUhHrTHK-ghc7.8.4.dylib - -- Referenced from: - -- /Users/travis/build/haskell/cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup-with-hpc.dist/dist/build/test-Short/test-Short - -- Reason: image not found - -- - -- This should get fixed eventually, but not today as I don't - -- have an actual Mac OS X box to debug on. - setupAndCabalTest . recordMode DoNotRecord $ do - let name | null suffixes = "Vanilla" - | otherwise = intercalate "-" suffixes - where - suffixes = catMaybes - [ if libProf then Just "LibProf" else Nothing - , if exeProf then Just "ExeProf" else Nothing - , if exeDyn then Just "ExeDyn" else Nothing - , if shared then Just "Shared" else Nothing - ] - opts = catMaybes - [ enable libProf "library-profiling" - , enable exeProf "profiling" - , enable exeDyn "executable-dynamic" - , enable shared "shared" - ] - where - enable cond flag - | cond = Just $ "--enable-" ++ flag - | otherwise = Nothing - -- Ensure that both .tix file and markup are generated if coverage - -- is enabled. - shared_libs <- hasSharedLibraries - prof_libs <- hasProfiledLibraries - unless ((exeDyn || shared) && not shared_libs) $ do - unless ((libProf || exeProf) && not prof_libs) $ do - isCorrectVersion <- liftIO $ correctHpcVersion - when isCorrectVersion $ do - dist_dir <- fmap testDistDir getTestEnv - setup_build ("--enable-tests" : "--enable-coverage" : opts) - setup "test" ["test-Short", "--show-details=direct"] - lbi <- getLocalBuildInfoM - let way = guessWay lbi - CompilerId comp version = compilerId (compiler lbi) - subdir - | comp == GHC && version >= mkVersion [7,10] = - localCompatPackageKey lbi - | otherwise = display (localPackage lbi) - mapM_ shouldExist - [ mixDir dist_dir way "my-0.1" subdir "Foo.mix" - , mixDir dist_dir way "test-Short" "Main.mix" - , tixFilePath dist_dir way "test-Short" - , htmlDir dist_dir way "test-Short" "hpc_index.html" - ] - where - choose4 :: [a] -> [(a, a, a, a)] - choose4 xs = liftM4 (,,,) xs xs xs xs - --- | Checks for a suitable HPC version for testing. -correctHpcVersion :: IO Bool -correctHpcVersion = do - let programDb' = emptyProgramDb - let verbosity = Verbosity.normal - let verRange = orLaterVersion (mkVersion [0,7]) - programDb <- configureProgram verbosity hpcProgram programDb' - (requireProgramVersion verbosity hpcProgram verRange programDb - >> return True) `catchIO` (\_ -> return False) - where - -- Distribution.Compat.Exception is hidden. - catchIO :: IO a -> (E.IOException -> IO a) -> IO a - catchIO = E.catch diff --git a/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup-with-hpc.out b/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup-with-hpc.out deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup.out b/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup.out deleted file mode 100644 index 315b15850c6..00000000000 --- a/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup.out +++ /dev/null @@ -1,18 +0,0 @@ -# Setup configure -Configuring my-0.1... -# Setup build -Preprocessing library for my-0.1.. -Building library for my-0.1.. -Preprocessing test suite 'test-Foo' for my-0.1.. -Building test suite 'test-Foo' for my-0.1.. -Preprocessing test suite 'test-Short' for my-0.1.. -Building test suite 'test-Short' for my-0.1.. -# Setup test -Running 2 test suites... -Test suite test-Foo: RUNNING... -Test suite test-Foo: PASS -Test suite logged to: setup.dist/work/dist/test/my-0.1-test-Foo.log -Test suite test-Short: RUNNING... -Test suite test-Short: PASS -Test suite logged to: setup.dist/work/dist/test/my-0.1-test-Short.log -2 of 2 test suites (2 of 2 test cases) passed. diff --git a/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup.test.hs b/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup.test.hs deleted file mode 100644 index 9b745106cc0..00000000000 --- a/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup.test.hs +++ /dev/null @@ -1,7 +0,0 @@ -import Test.Cabal.Prelude - -main = setupAndCabalTest $ do - setup_build ["--enable-tests"] - -- This one runs both tests, including the very LONG Foo - -- test which prints a lot of output - setup "test" ["--show-details=direct"] From 2592dc63f933ec15f10beb75c987066ab3fa43c2 Mon Sep 17 00:00:00 2001 From: Thomas Tuegel Date: Wed, 22 Nov 2017 11:10:04 -0600 Subject: [PATCH 2/2] Disable per-component build when program coverage enabled Creating the test program coverage report requires the test runner to know the build directory for the library component. If per-component builds are enabled, this is not possible because the library is not in-scope at the same time as the test component. The only apparent solution that does not require rethinking per-component builds entirely is to disable it when coverage is enabled. Resolves: #4798 --- cabal-install/Distribution/Client/ProjectPlanning.hs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cabal-install/Distribution/Client/ProjectPlanning.hs b/cabal-install/Distribution/Client/ProjectPlanning.hs index 0b30d8f3e63..8ac47320f24 100644 --- a/cabal-install/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/Distribution/Client/ProjectPlanning.hs @@ -1211,7 +1211,7 @@ elaborateInstallPlan verbosity platform compiler compilerprogdb pkgConfigDB where -- You are eligible to per-component build if this list is empty why_not_per_component g - = cuz_custom ++ cuz_spec ++ cuz_length ++ cuz_flag + = cuz_custom ++ cuz_spec ++ cuz_length ++ cuz_flag ++ cuz_coverage where cuz reason = [text reason] -- At this point in time, only non-Custom setup scripts @@ -1243,6 +1243,12 @@ elaborateInstallPlan verbosity platform compiler compilerprogdb pkgConfigDB | fromFlagOrDefault True (projectConfigPerComponent sharedPackageConfig) = [] | otherwise = cuz "you passed --disable-per-component" + -- Enabling program coverage introduces odd runtime dependencies + -- between components. + cuz_coverage + | fromFlagOrDefault False (packageConfigCoverage localPackagesConfig) + = cuz "program coverage is enabled" + | otherwise = [] -- | Sometimes a package may make use of features which are only -- supported in per-package mode. If this is the case, we should