Skip to content

Commit 786f132

Browse files
committed
Add exhaustive test suite for 'cabal path' cmd
We test that each query honours cabal.project files, cli parameters, and is composable with the other query flags. We extend the test output normalisers for ghc compiler location and cabal-install version, as the 'cabal path' command outputs the exact ghc and ghc-pkg location. In addition, the json output format is versioned on the cabal-install version. Currently, we query the cabal-install version on each test normalisation run. This might be unnecessary expensive, and could be avoided by introducing a 'cabalProgram' that specifies how the program version can be found. This way, we can cache the version query.
1 parent 6f637a8 commit 786f132

File tree

13 files changed

+638
-13
lines changed

13 files changed

+638
-13
lines changed

cabal-testsuite/PackageTests/Path/All/cabal.out

Lines changed: 447 additions & 0 deletions
Large diffs are not rendered by default.

cabal-testsuite/PackageTests/Path/All/cabal.test.hs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,27 @@
11
import Test.Cabal.Prelude
2+
import Data.List (subsequences)
3+
4+
allOutputFormats =
5+
[ "json"
6+
, "key-value"
7+
]
8+
9+
allFlags =
10+
[ "--compiler-info"
11+
, "--cache-dir"
12+
, "--logs-dir"
13+
, "--store-dir"
14+
, "--config-file"
15+
, "--installdir"
16+
]
17+
18+
main = cabalTest $ do
19+
forM_ allOutputFormats $ \outputFormat -> do
20+
-- Order of flags should not matter, neither does any flag depend on the
21+
-- existence of any other flag.
22+
--
23+
-- 'subsequences' generated "n over k" for k in (1 .. n)
24+
forM_ (subsequences allFlags) $ \flags -> do
25+
cabal "path" $ ["--output-format", outputFormat] <> flags
26+
227

3-
main = cabalTest . void $ cabal "path" ["-z", "--output-format=key-value"]
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# cabal path
2+
compiler-flavour: ghc
3+
compiler-id: ghc-<GHCVER>
4+
compiler-path: <GHCPATH>
5+
# cabal path
6+
{"cabal-install-version":"<CABAL_INSTALL_VER>","compiler":{"flavour":"ghc","id":"ghc-<GHCVER>","path":"<GHCPATH>"}}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import Test.Cabal.Prelude
2+
3+
main = cabalTest $ do
4+
-- Basic output
5+
void $ cabal "path" ["-z", "--output-format=key-value", "--compiler-info"]
6+
void $ cabal "path" ["-z", "--output-format=json", "--compiler-info"]
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# cabal path
2+
<ROOT>/cabal.dist/home/.cabal/packages
3+
# cabal path
4+
<ROOT>/cabal.dist/home/.cabal/logs
5+
# cabal path
6+
<ROOT>/cabal.dist/home/.cabal/store
7+
# cabal path
8+
<ROOT>/cabal.dist/home/.cabal/config
9+
# cabal path
10+
<ROOT>/cabal.dist/home/.cabal/bin
11+
# cabal path
12+
{"cabal-install-version":"<CABAL_INSTALL_VER>","cache-dir":"<ROOT>/cabal.dist/home/.cabal/packages"}
13+
# cabal path
14+
{"cabal-install-version":"<CABAL_INSTALL_VER>","logs-dir":"<ROOT>/cabal.dist/home/.cabal/logs"}
15+
# cabal path
16+
{"cabal-install-version":"<CABAL_INSTALL_VER>","store-dir":"<ROOT>/cabal.dist/home/.cabal/store"}
17+
# cabal path
18+
{"cabal-install-version":"<CABAL_INSTALL_VER>","config-file":"<ROOT>/cabal.dist/home/.cabal/config"}
19+
# cabal path
20+
{"cabal-install-version":"<CABAL_INSTALL_VER>","installdir":"<ROOT>/cabal.dist/home/.cabal/bin"}
21+
# cabal path
22+
test-dir
23+
# cabal path
24+
{"cabal-install-version":"<CABAL_INSTALL_VER>","store-dir":"test-dir"}
25+
# cabal path
26+
my-cache-dir
27+
# cabal path
28+
my-logs-dir
29+
# cabal path
30+
my-store-dir
31+
# cabal path
32+
fake-cabal.config
33+
# cabal path
34+
my-installdir
35+
# cabal path
36+
{"cabal-install-version":"<CABAL_INSTALL_VER>","cache-dir":"my-cache-dir"}
37+
# cabal path
38+
{"cabal-install-version":"<CABAL_INSTALL_VER>","logs-dir":"my-logs-dir"}
39+
# cabal path
40+
{"cabal-install-version":"<CABAL_INSTALL_VER>","store-dir":"my-store-dir"}
41+
# cabal path
42+
{"cabal-install-version":"<CABAL_INSTALL_VER>","config-file":"fake-cabal.config"}
43+
# cabal path
44+
{"cabal-install-version":"<CABAL_INSTALL_VER>","installdir":"my-installdir"}
45+
# cabal path
46+
my-cache-dir
47+
# cabal path
48+
my-logs-dir
49+
# cabal path
50+
my-store-dir
51+
# cabal path
52+
<ROOT>/cabal.dist/home/.cabal/config
53+
# cabal path
54+
my-installdir
55+
# cabal path
56+
{"cabal-install-version":"<CABAL_INSTALL_VER>","cache-dir":"my-cache-dir"}
57+
# cabal path
58+
{"cabal-install-version":"<CABAL_INSTALL_VER>","logs-dir":"my-logs-dir"}
59+
# cabal path
60+
{"cabal-install-version":"<CABAL_INSTALL_VER>","store-dir":"my-store-dir"}
61+
# cabal path
62+
{"cabal-install-version":"<CABAL_INSTALL_VER>","config-file":"<ROOT>/cabal.dist/home/.cabal/config"}
63+
# cabal path
64+
{"cabal-install-version":"<CABAL_INSTALL_VER>","installdir":"my-installdir"}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import Test.Cabal.Prelude
2+
3+
main = cabalTest $ do
4+
-- Basic output
5+
void $ cabal "path" ["-z", "--output-format=key-value", "--cache-dir"]
6+
void $ cabal "path" ["-z", "--output-format=key-value", "--logs-dir"]
7+
void $ cabal "path" ["-z", "--output-format=key-value", "--store-dir"]
8+
void $ cabal "path" ["-z", "--output-format=key-value", "--config-file"]
9+
void $ cabal "path" ["-z", "--output-format=key-value", "--installdir"]
10+
-- Works for json, too
11+
void $ cabal "path" ["-z", "--output-format=json", "--cache-dir"]
12+
void $ cabal "path" ["-z", "--output-format=json", "--logs-dir"]
13+
void $ cabal "path" ["-z", "--output-format=json", "--store-dir"]
14+
void $ cabal "path" ["-z", "--output-format=json", "--config-file"]
15+
void $ cabal "path" ["-z", "--output-format=json", "--installdir"]
16+
-- Honours cli overwrites
17+
void $ cabalG ["--store-dir=test-dir"] "path" ["-z", "--output-format=key-value", "--store-dir"]
18+
void $ cabalG ["--store-dir=test-dir"] "path" ["-z", "--output-format=json", "--store-dir"]
19+
-- Honour config file overwrites:
20+
void $ cabalG ["--config-file=fake-cabal.config"] "path" ["-z", "--output-format=key-value", "--cache-dir"]
21+
void $ cabalG ["--config-file=fake-cabal.config"] "path" ["-z", "--output-format=key-value", "--logs-dir"]
22+
void $ cabalG ["--config-file=fake-cabal.config"] "path" ["-z", "--output-format=key-value", "--store-dir"]
23+
void $ cabalG ["--config-file=fake-cabal.config"] "path" ["-z", "--output-format=key-value", "--config-file"]
24+
void $ cabalG ["--config-file=fake-cabal.config"] "path" ["-z", "--output-format=key-value", "--installdir"]
25+
26+
void $ cabalG ["--config-file=fake-cabal.config"] "path" ["-z", "--output-format=json", "--cache-dir"]
27+
void $ cabalG ["--config-file=fake-cabal.config"] "path" ["-z", "--output-format=json", "--logs-dir"]
28+
void $ cabalG ["--config-file=fake-cabal.config"] "path" ["-z", "--output-format=json", "--store-dir"]
29+
void $ cabalG ["--config-file=fake-cabal.config"] "path" ["-z", "--output-format=json", "--config-file"]
30+
void $ cabalG ["--config-file=fake-cabal.config"] "path" ["-z", "--output-format=json", "--installdir"]
31+
32+
-- Honour cabal.project file
33+
void $ cabal "path" ["--project-file=fake.cabal.project", "--output-format=key-value", "--cache-dir"]
34+
void $ cabal "path" ["--project-file=fake.cabal.project", "--output-format=key-value", "--logs-dir"]
35+
void $ cabal "path" ["--project-file=fake.cabal.project", "--output-format=key-value", "--store-dir"]
36+
void $ cabal "path" ["--project-file=fake.cabal.project", "--output-format=key-value", "--config-file"]
37+
void $ cabal "path" ["--project-file=fake.cabal.project", "--output-format=key-value", "--installdir"]
38+
-- Works for json, too
39+
void $ cabal "path" ["--project-file=fake.cabal.project", "--output-format=json", "--cache-dir"]
40+
void $ cabal "path" ["--project-file=fake.cabal.project", "--output-format=json", "--logs-dir"]
41+
void $ cabal "path" ["--project-file=fake.cabal.project", "--output-format=json", "--store-dir"]
42+
void $ cabal "path" ["--project-file=fake.cabal.project", "--output-format=json", "--config-file"]
43+
void $ cabal "path" ["--project-file=fake.cabal.project", "--output-format=json", "--installdir"]
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
cabal-version: 3.0
2+
name: config
3+
version: 0.1
4+
5+
library
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
-- this is a test file, dont use it
2+
repository hackage.haskell.org
3+
url: http://hackage.haskell.org/
4+
-- secure: True
5+
-- root-keys:
6+
-- key-threshold: 3
7+
8+
logs-dir: my-logs-dir
9+
store-dir: my-store-dir
10+
remote-repo-cache: my-cache-dir
11+
installdir: my-installdir
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
packages: ./
2+
3+
logs-dir: my-logs-dir
4+
store-dir: my-store-dir
5+
remote-repo-cache: my-cache-dir
6+
installdir: my-installdir

cabal-testsuite/PackageTests/Path/Single/cabal.out

Lines changed: 0 additions & 2 deletions
This file was deleted.

cabal-testsuite/PackageTests/Path/Single/cabal.test.hs

Lines changed: 0 additions & 3 deletions
This file was deleted.

cabal-testsuite/src/Test/Cabal/Monad.hs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -300,9 +300,7 @@ runTestM mode m =
300300
program_db1
301301
verbosity
302302

303-
ghcLocation <- case lookupProgramByName "ghc" program_db2 of
304-
Nothing -> fail "runTestM.lookupProgramByName: No location for 'ghc' was found"
305-
Just ghcProg -> pure $ programPath ghcProg
303+
(configuredGhcProg, _) <- requireProgram verbosity ghcProgram program_db2
306304

307305
program_db3 <-
308306
reconfigurePrograms verbosity
@@ -325,7 +323,7 @@ runTestM mode m =
325323
testProgramDb = program_db,
326324
testPlatform = platform,
327325
testCompiler = comp,
328-
testCompilerPath = ghcLocation,
326+
testCompilerPath = programPath configuredGhcProg,
329327
testPackageDBStack = db_stack,
330328
testVerbosity = verbosity,
331329
testMtimeChangeDelay = Nothing,
@@ -530,6 +528,16 @@ mkNormalizerEnv = do
530528

531529
canonicalizedTestTmpDir <- liftIO $ canonicalizePath (testTmpDir env)
532530

531+
-- 'cabal' is configured in the package-db, but doesn't specify how to find the program version
532+
-- Thus we find the program location, if it exists, and query for the program version for
533+
-- output normalisation.
534+
cabalVersionM <- do
535+
cabalProgM <- needProgramM "cabal"
536+
case cabalProgM of
537+
Nothing -> pure Nothing
538+
Just cabalProg -> do
539+
liftIO (findProgramVersion "--numeric-version" id (testVerbosity env) (programPath cabalProg))
540+
533541
return NormalizerEnv {
534542
normalizerRoot
535543
= addTrailingPathSeparator (testSourceDir env),
@@ -548,7 +556,9 @@ mkNormalizerEnv = do
548556
normalizerPlatform
549557
= testPlatform env,
550558
normalizerCabalVersion
551-
= cabalVersionLibrary
559+
= cabalVersionLibrary,
560+
normalizerCabalInstallVersion
561+
= cabalVersionM
552562
}
553563

554564
cabalVersionLibrary :: Version
@@ -561,6 +571,11 @@ requireProgramM program = do
561571
requireProgram (testVerbosity env) program (testProgramDb env)
562572
return configured_program
563573

574+
needProgramM :: String -> TestM (Maybe ConfiguredProgram)
575+
needProgramM program = do
576+
env <- getTestEnv
577+
return $ lookupProgramByName program (testProgramDb env)
578+
564579
programPathM :: Program -> TestM FilePath
565580
programPathM program = do
566581
fmap programPath (requireProgramM program)

cabal-testsuite/src/Test/Cabal/OutputNormalizer.hs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,20 +63,22 @@ normalizeOutput nenv =
6363
"<GHCVER>"
6464
else id)
6565
. normalizeBuildInfoJson
66-
. normalizePathCmdOutput
66+
. maybe id normalizePathCmdOutput (normalizerCabalInstallVersion nenv)
6767
-- hackage-security locks occur non-deterministically
6868
. resub "(Released|Acquired|Waiting) .*hackage-security-lock\n" ""
6969
where
7070
packageIdRegex pid =
7171
resub (posixRegexEscape (display pid) ++ "(-[A-Za-z0-9.-]+)?")
7272
(prettyShow (packageName pid) ++ "-<VERSION>")
7373

74-
normalizePathCmdOutput =
74+
normalizePathCmdOutput cabalInstallVersion =
7575
-- clear the ghc path out of all supported output formats
7676
resub ("compiler-path: " <> posixRegexEscape (normalizerGhcPath nenv))
7777
"compiler-path: <GHCPATH>"
7878
. resub ("\"compiler-path\"\\s*:\\s*\"" <> posixRegexEscape (normalizerGhcPath nenv) <> "\"")
7979
"\"compiler-path\": \"<GHCPATH>\""
80+
. resub (display cabalInstallVersion)
81+
"<CABAL_INSTALL_VER>"
8082

8183
-- 'build-info.json' contains a plethora of host system specific information.
8284
--
@@ -116,6 +118,7 @@ data NormalizerEnv = NormalizerEnv
116118
, normalizerKnownPackages :: [PackageId]
117119
, normalizerPlatform :: Platform
118120
, normalizerCabalVersion :: Version
121+
, normalizerCabalInstallVersion :: Maybe Version
119122
}
120123

121124
posixSpecialChars :: [Char]

0 commit comments

Comments
 (0)