Skip to content

Commit 0c0e115

Browse files
committed
Add test for multi-repl hie bios
Verify that we are getting the expected unit files and that for sources, includes and dependencies, the unit files have the correct contents.
1 parent 9b28e9d commit 0c0e115

File tree

7 files changed

+127
-10
lines changed

7 files changed

+127
-10
lines changed

rules_haskell_tests/tests/RunTests.hs

Lines changed: 91 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,21 @@
33
{-# LANGUAGE FlexibleContexts #-}
44
{-# LANGUAGE QuasiQuotes #-}
55

6-
import Control.Exception.Safe (bracket_)
6+
import Control.Exception.Safe (bracket, bracket_)
77
import Data.Foldable (for_)
8-
import Data.List (isInfixOf, sort)
8+
import Data.List (delete, intercalate, isInfixOf, isPrefixOf, isSuffixOf, sort, stripPrefix)
99
import GHC.Stack (HasCallStack)
1010
import System.Directory (copyFile, doesFileExist)
1111
import System.FilePath ((</>))
1212
import System.Info (os)
13+
import System.IO (IOMode (..), hClose, hGetContents', openFile)
1314
import System.IO.Temp (withSystemTempDirectory)
1415
import System.Environment (lookupEnv)
1516
import System.Exit (ExitCode(..))
1617

1718
import qualified System.Process as Process
1819
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)
2021

2122
import BinModule (b)
2223
import GenModule (a)
@@ -100,16 +101,100 @@ main = hspec $ around_ printStatsHook $ do
100101

101102
describe "multi_repl" $ do
102103
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"]
104105
outputSatisfy p' (bazel ["run", "//tests/multi_repl:c_only_repl", "--", "-ignore-dot-ghci", "-e", ":show targets"])
105106
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"]
107108
outputSatisfy p' (bazel ["run", "//tests/multi_repl:c_multi_repl", "--", "-ignore-dot-ghci", "-e", ":show targets"])
108109
it "loads core library dependencies" $ do
109110
let p' (stdout, _stderr) = sort (lines stdout) == ["tests/multi_repl/core_package_dep/Lib.hs"]
110111
outputSatisfy p' (bazel ["run", "//tests/multi_repl:core_package_dep", "--", "-ignore-dot-ghci", "-e", ":show targets"])
111112
it "doesn't allow to manually load modules" $ do
112113
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"])
113198

114199
describe "ghcide" $ do
115200
it "loads RunTests.hs" $
@@ -144,7 +229,7 @@ main = hspec $ around_ printStatsHook $ do
144229

145230
-- Test that the repl still works if we shadow some Prelude functions
146231
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]
148233
outputSatisfy p (bazel ["run", "//tests/repl-name-conflicts:lib@repl", "--", "-ignore-dot-ghci", "-e", "stdin"])
149234

150235
-- GH2096: This test is flaky in CI using the MacOS GitHub runners. The flakiness is slowing

rules_haskell_tests/tests/multi_repl/BUILD.bazel

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ haskell_repl(
2020
deps = ["//tests/multi_repl/core_package_dep"],
2121
)
2222

23+
haskell_repl(
24+
name = "d_unit_repl",
25+
deps = ["//tests/multi_repl/bc:d"],
26+
multi = True,
27+
)
28+
2329
filegroup(
2430
name = "all_files",
2531
testonly = True,

rules_haskell_tests/tests/multi_repl/a/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ haskell_library(
1414
deps = [
1515
"//tests/hackage:base",
1616
],
17+
package_name = "a",
18+
version = "0.0.0",
1719
)
1820

1921
filegroup(

rules_haskell_tests/tests/multi_repl/bc/BUILD.bazel

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,43 @@ package(default_visibility = ["//visibility:public"])
88
haskell_library(
99
name = "b",
1010
srcs = [
11-
"src/BC/B.hs",
11+
"src-b/BC/B.hs",
1212
],
13-
src_strip_prefix = "src",
13+
src_strip_prefix = "src-b",
1414
deps = [
1515
"//tests/hackage:base",
1616
"//tests/multi_repl/a",
1717
],
18+
package_name = "b",
19+
version = "0.0.0",
1820
)
1921

2022
haskell_library(
2123
name = "c",
2224
srcs = [
23-
"src/BC/C.hs",
25+
"src-c/BC/C.hs",
2426
],
25-
src_strip_prefix = "src",
27+
src_strip_prefix = "src-c",
2628
deps = [
2729
":b",
2830
"//tests/hackage:base",
2931
],
32+
package_name = "c",
33+
version = "0.0.0",
34+
)
35+
36+
haskell_library(
37+
name = "d",
38+
srcs = [
39+
"src-d/BC/D.hs",
40+
],
41+
src_strip_prefix = "src-d",
42+
deps = [
43+
":c",
44+
"//tests/hackage:base",
45+
],
46+
package_name = "d",
47+
version = "0.0.0",
3048
)
3149

3250
filegroup(
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module BC.D ( d ) where
2+
3+
import BC.C ( c )
4+
5+
d :: ()
6+
d = c

0 commit comments

Comments
 (0)