|
3 | 3 | {-# LANGUAGE FlexibleContexts #-}
|
4 | 4 | {-# LANGUAGE QuasiQuotes #-}
|
5 | 5 |
|
6 |
| -import Control.Exception.Safe (bracket_) |
| 6 | +import Control.Exception.Safe (bracket, bracket_) |
7 | 7 | import Data.Foldable (for_)
|
8 |
| -import Data.List (isInfixOf, sort) |
| 8 | +import Data.List (delete, intercalate, isInfixOf, isPrefixOf, isSuffixOf, sort, stripPrefix) |
9 | 9 | import GHC.Stack (HasCallStack)
|
10 | 10 | import System.Directory (copyFile, doesFileExist)
|
11 | 11 | import System.FilePath ((</>))
|
12 | 12 | import System.Info (os)
|
| 13 | +import System.IO (IOMode (..), hClose, hGetContents', openFile) |
13 | 14 | import System.IO.Temp (withSystemTempDirectory)
|
14 | 15 | import System.Environment (lookupEnv)
|
15 | 16 | import System.Exit (ExitCode(..))
|
16 | 17 |
|
17 | 18 | import qualified System.Process as Process
|
18 | 19 | import Test.Hspec.Core.Spec (SpecM, SpecWith)
|
19 |
| -import Test.Hspec (context, hspec, it, describe, runIO, around_, afterAll_) |
| 20 | +import Test.Hspec (context, hspec, it, describe, runIO, around_, afterAll_, expectationFailure, shouldBe) |
20 | 21 |
|
21 | 22 | import BinModule (b)
|
22 | 23 | import GenModule (a)
|
@@ -100,16 +101,100 @@ main = hspec $ around_ printStatsHook $ do
|
100 | 101 |
|
101 | 102 | describe "multi_repl" $ do
|
102 | 103 | it "loads transitive library dependencies" $ do
|
103 |
| - let p' (stdout, _stderr) = lines stdout == ["tests/multi_repl/bc/src/BC/C.hs"] |
| 104 | + let p' (stdout, _stderr) = lines stdout == ["tests/multi_repl/bc/src-c/BC/C.hs"] |
104 | 105 | outputSatisfy p' (bazel ["run", "//tests/multi_repl:c_only_repl", "--", "-ignore-dot-ghci", "-e", ":show targets"])
|
105 | 106 | it "loads transitive source dependencies" $ do
|
106 |
| - let p' (stdout, _stderr) = sort (lines stdout) == ["tests/multi_repl/a/src/A/A.hs","tests/multi_repl/bc/src/BC/B.hs","tests/multi_repl/bc/src/BC/C.hs"] |
| 107 | + let p' (stdout, _stderr) = sort (lines stdout) == ["tests/multi_repl/a/src/A/A.hs","tests/multi_repl/bc/src-b/BC/B.hs","tests/multi_repl/bc/src-c/BC/C.hs"] |
107 | 108 | outputSatisfy p' (bazel ["run", "//tests/multi_repl:c_multi_repl", "--", "-ignore-dot-ghci", "-e", ":show targets"])
|
108 | 109 | it "loads core library dependencies" $ do
|
109 | 110 | let p' (stdout, _stderr) = sort (lines stdout) == ["tests/multi_repl/core_package_dep/Lib.hs"]
|
110 | 111 | outputSatisfy p' (bazel ["run", "//tests/multi_repl:core_package_dep", "--", "-ignore-dot-ghci", "-e", ":show targets"])
|
111 | 112 | it "doesn't allow to manually load modules" $ do
|
112 | 113 | assertFailure (bazel ["run", "//tests/multi_repl:c_multi_repl", "--", "-ignore-dot-ghci", "-e", ":load BC.C", "-e", "c"])
|
| 114 | + it "produces correct unit files for a repl flagged multi" $ do |
| 115 | + let unitFiles = ["a_a_unit_file", "bc_b_unit_file", "bc_c_unit_file", "bc_d_unit_file"] |
| 116 | + makeExpected prefix = |
| 117 | + [ "-hide-all-packages" ] |
| 118 | + ++ concatMap (\unitFile -> |
| 119 | + [ "-unit" |
| 120 | + , prefix ++ unitFile |
| 121 | + ] |
| 122 | + ) unitFiles |
| 123 | + stripPrefix' pfx object = |
| 124 | + case stripPrefix pfx object of |
| 125 | + Nothing -> error "unexpected prefix strip failure" |
| 126 | + Just stripped -> stripped |
| 127 | + readLines :: FilePath -> IO [String] |
| 128 | + readLines filePath = bracket |
| 129 | + (openFile filePath ReadMode) |
| 130 | + (hClose) |
| 131 | + (\h -> lines <$> hGetContents' h) |
| 132 | + checkUnitFile :: FilePath -> [String] -> [FilePath] -> [FilePath] -> IO () |
| 133 | + checkUnitFile unitFile startDeps startSources startIncludes = do |
| 134 | + unitArgs <- readLines unitFile |
| 135 | + go unitArgs startDeps startSources startIncludes |
| 136 | + where |
| 137 | + go [] [] [] [] = pure () |
| 138 | + go [] deps sources includes = expectationFailure( |
| 139 | + "At least one of expected (dependecies, sources, include directories) was not-found:" |
| 140 | + ++ (if (null deps) then "" else " missing dependencies: " ++ show deps) |
| 141 | + ++ (if (null sources) then "" else " missing sources: " ++ show sources) |
| 142 | + ++ (if (null includes) then "" else " missing include directories: " ++ show includes) |
| 143 | + ) |
| 144 | + go ("-package-id":pkgId:rest) deps sources includes = |
| 145 | + if "base" `isPrefixOf` pkgId |
| 146 | + then go rest deps sources includes |
| 147 | + else if pkgId `elem` deps |
| 148 | + then go rest (delete pkgId deps) sources includes |
| 149 | + else expectationFailure ("unexpected dependency: " ++ pkgId) |
| 150 | + go (x:rest) deps sources includes | "-i" `isPrefixOf` x = |
| 151 | + let includeDir = drop 2 x |
| 152 | + in if includeDir `elem` includes |
| 153 | + then go rest deps sources (delete includeDir includes) |
| 154 | + else expectationFailure ("unexpected include dir: " ++ x ++ "\n" ++ "expected includes:\n" ++ (intercalate "\n" startIncludes)) |
| 155 | + go (x:rest) deps sources includes | "tests/" `isPrefixOf` x = |
| 156 | + if x `elem` sources |
| 157 | + then go rest deps (delete x sources) includes |
| 158 | + else expectationFailure ("unexpected source file: " ++ x) |
| 159 | + go (_:rest) deps sources includes | otherwise = go rest deps sources includes |
| 160 | + checkUnitFiles :: Process.CreateProcess -> IO () |
| 161 | + checkUnitFiles cmd = do |
| 162 | + (exitCode, stdout, stderrCapture) <- Process.readCreateProcessWithExitCode cmd "" |
| 163 | + case exitCode of |
| 164 | + ExitFailure _ -> expectationFailure (formatOutput exitCode stdout stderrCapture) |
| 165 | + ExitSuccess -> do |
| 166 | + let stdoutLines = lines stdout |
| 167 | + case take 1 $ filter ("a_a_unit_file" `isSuffixOf`) stdoutLines of |
| 168 | + [] -> expectationFailure "Could not find prefix to read unit files." |
| 169 | + (_:_:_) -> error "take 1 returned a list of length 2 or greater" |
| 170 | + [fullAUnitFile] -> do |
| 171 | + let atPrefix = stripSuffix' "a_a_unit_file" fullAUnitFile |
| 172 | + prefix = stripPrefix' "@" atPrefix |
| 173 | + shortPrefix = stripSuffix' "_tests/multi_repl/" prefix |
| 174 | + stripSuffix' sfx target = reverse $ stripPrefix' (reverse sfx) $ reverse target |
| 175 | + expandPath f = prefix ++ f |
| 176 | + lines stdout `shouldBe` makeExpected atPrefix |
| 177 | + checkUnitFile |
| 178 | + (expandPath "a_a_unit_file") |
| 179 | + [] |
| 180 | + ["tests/multi_repl/a/src/A/A.hs"] |
| 181 | + ["tests/multi_repl/a/src", shortPrefix ++ "a/src"] |
| 182 | + checkUnitFile |
| 183 | + (expandPath "bc_b_unit_file") |
| 184 | + ["testsZSmultiZUreplZSaZSa"] |
| 185 | + ["tests/multi_repl/bc/src-b/BC/B.hs"] |
| 186 | + ["tests/multi_repl/bc/src-b", shortPrefix ++ "bc/src-b"] |
| 187 | + checkUnitFile |
| 188 | + (expandPath "bc_c_unit_file") |
| 189 | + ["testsZSmultiZUreplZSbcZSb"] |
| 190 | + ["tests/multi_repl/bc/src-c/BC/C.hs"] |
| 191 | + ["tests/multi_repl/bc/src-c", shortPrefix ++ "bc/src-c"] |
| 192 | + checkUnitFile |
| 193 | + (expandPath "bc_d_unit_file") |
| 194 | + ["testsZSmultiZUreplZSbcZSc"] |
| 195 | + ["tests/multi_repl/bc/src-d/BC/D.hs"] |
| 196 | + ["tests/multi_repl/bc/src-d", shortPrefix ++ "bc/src-d"] |
| 197 | + checkUnitFiles (bazel ["run", "//tests/multi_repl:d_unit_repl@bios"]) |
113 | 198 |
|
114 | 199 | describe "ghcide" $ do
|
115 | 200 | it "loads RunTests.hs" $
|
@@ -144,7 +229,7 @@ main = hspec $ around_ printStatsHook $ do
|
144 | 229 |
|
145 | 230 | -- Test that the repl still works if we shadow some Prelude functions
|
146 | 231 | it "repl name shadowing" $ do
|
147 |
| - let p (stdout, stderr) = not $ any ("error" `isInfixOf`) [stdout, stderr] |
| 232 | + let p (stdout, stderrCapture) = not $ any ("error" `isInfixOf`) [stdout, stderrCapture] |
148 | 233 | outputSatisfy p (bazel ["run", "//tests/repl-name-conflicts:lib@repl", "--", "-ignore-dot-ghci", "-e", "stdin"])
|
149 | 234 |
|
150 | 235 | -- GH2096: This test is flaky in CI using the MacOS GitHub runners. The flakiness is slowing
|
|
0 commit comments