Skip to content

Commit

Permalink
Multliline expectations
Browse files Browse the repository at this point in the history
- Add else.project test
- Use normalizeWindowsOutput
- Add a changelog entry
- Update expectation
- Use concatOutput on needle
- Include output
- Align lines
- Show modified output
- Apply concatOutput to the needle
- Show start and end of lines with ASCII ^ and $h
- Can't print pilcrow so use grep char for marking end of line
- Marking the start of line distinguishes "expected" intro from its content too, same for "output"
- Use \n in multiline string expectation
  • Loading branch information
philderbeast committed Jan 1, 2025
1 parent dd21a74 commit 8a5a5b4
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import Test.Cabal.Prelude

normalizeWindowsOutput :: String -> String
normalizeWindowsOutput = if isWindows then map (\x -> case x of '/' -> '\\'; _ -> x) else id

main = cabalTest . withRepo "repo" . recordMode RecordMarked $ do
let log = recordHeader . pure

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# cabal v2-build
Warning: <ROOT>/else.project, else.project: Unrecognized section '_' on line 3
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Test.Cabal.Prelude

main = cabalTest . recordMode RecordMarked $ do
let log = recordHeader . pure

outElse <- fails $ cabal' "v2-build" [ "all", "--dry-run", "--project-file=else.project" ]
assertOutputContainsOn unConcatOutput unConcatOutput concatOutput
(concatOutput "When using configuration from:\n\
\ - else.project\n\
\ - dir-else/else.config\n\
\The following errors occurred:\n\
\ - The package location 'no-pkg-here' does not exist.")
outElse

return ()
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
if false
else
_
packages: no-pkg-here
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import: dir-else/else.config
60 changes: 48 additions & 12 deletions cabal-testsuite/src/Test/Cabal/Prelude.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
{-# LANGUAGE NondecreasingIndentation #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE ViewPatterns #-}

-- | Generally useful definitions that we expect most test scripts
-- to use.
Expand Down Expand Up @@ -795,19 +796,31 @@ recordMode mode = withReaderT (\env -> env {
testRecordUserMode = Just mode
})

assertOutputContains :: MonadIO m => WithCallStack (String -> Result -> m ())
assertOutputContains needle result =
assertOutputContainsOn :: MonadIO m => WithCallStack ((String -> String) -> (String -> String) -> (String -> String) -> (String -> String) -> String -> Result -> m ())
assertOutputContainsOn unN n unO o (n -> needle) (o . resultOutput -> output) =
withFrozenCallStack $
unless (needle `isInfixOf` (concatOutput output)) $
assertFailure $ " expected: " ++ needle
where output = resultOutput result
unless (n needle `isInfixOf` output) $
assertFailure $ "expected:\n" ++ unN needle ++
"\nin output:\n" ++ unO output

assertOutputDoesNotContain :: MonadIO m => WithCallStack (String -> Result -> m ())
assertOutputDoesNotContain needle result =
assertOutputDoesNotContainOn :: MonadIO m => WithCallStack ((String -> String) -> (String -> String) -> (String -> String) -> (String -> String) -> String -> Result -> m ())
assertOutputDoesNotContainOn unN n unO o (n -> needle) (o . resultOutput -> output) =
withFrozenCallStack $
when (needle `isInfixOf` (concatOutput output)) $
assertFailure $ "unexpected: " ++ needle
where output = resultOutput result
when (needle `isInfixOf` output) $
assertFailure $ "unexpected:\n" ++ unN needle ++
"\nin output:\n" ++ unO output

assertOutputContains :: MonadIO m => WithCallStack (String -> Result -> m ())
assertOutputContains = assertOutputContainsOn id id unConcatOutput concatOutput

assertOutputDoesNotContain :: MonadIO m => WithCallStack (String -> Result -> m ())
assertOutputDoesNotContain = assertOutputDoesNotContainOn id id unConcatOutput concatOutput

assertOutputContainsMultiline :: MonadIO m => WithCallStack (String -> Result -> m ())
assertOutputContainsMultiline = assertOutputContainsOn unConcatOutput concatOutput unConcatOutput concatOutput

assertOutputDoesNotContainMultiline :: MonadIO m => WithCallStack (String -> Result -> m ())
assertOutputDoesNotContainMultiline = assertOutputDoesNotContainOn unConcatOutput concatOutput unConcatOutput concatOutput

assertFindInFile :: MonadIO m => WithCallStack (String -> FilePath -> m ())
assertFindInFile needle path =
Expand Down Expand Up @@ -861,9 +874,29 @@ assertNoFileContains paths needle =
\path ->
assertFileDoesNotContain path needle

-- | Replace line breaks with spaces, correctly handling "\r\n".
-- | Replace line breaks with <LF>, correctly handling "\r\n".
concatOutput :: String -> String
concatOutput = unwords . lines . filter ((/=) '\r')
concatOutput =
(\s -> if "<LF>" `isPrefixOf` s then drop 4 s else s) .
concat . (fmap ("<LF>" ++)) . lines . filter ((/=) '\r')

-- | Replace <LF> markers with line breaks and wrap lines with ^ and $ markers
-- for the start and end.
unConcatOutput :: String -> String
unConcatOutput output =
(\xs -> case lines xs of [line0] -> line0 ++ "$"; _ -> xs)
. unlines
. (fmap ('^' :))
. lines
. (\s -> if "<LF>" `isPrefixOf` s then drop 4 s else s)
$ foldr
(\c acc -> c :
if ("<LF>" `isPrefixOf` acc)
then "$\n" ++ drop 4 acc
else acc
)
""
output

-- | The directory where script build artifacts are expected to be cached
getScriptCacheDirectory :: FilePath -> TestM FilePath
Expand Down Expand Up @@ -1093,6 +1126,9 @@ flakyIfCI ticket m = do
flakyIfWindows :: IssueID -> TestM a -> TestM a
flakyIfWindows ticket m = flakyIf isWindows ticket m

normalizeWindowsOutput :: String -> String
normalizeWindowsOutput = if isWindows then map (\x -> case x of '/' -> '\\'; _ -> x) else id

getOpenFilesLimit :: TestM (Maybe Integer)
#ifdef mingw32_HOST_OS
-- No MS-specified limit, was determined experimentally on Windows 10 Pro x64,
Expand Down
34 changes: 34 additions & 0 deletions changelog.d/pr-10646
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
synopsis: Deduplicate path separator duplicates
packages: [cabal-install-solver]
prs: 10646
issues: 10645
---

The "using configuration from" message no longer has duplicates on Windows when
the `cabal.project` uses forward slashes for its imports but the message reports
imports with backslashes.

```diff
$ cat cabal.project
import: dir-a/b.config

$ cabal build all --dry-run
...
When using configuration from:
- - dir-a/b.config
- dir-a\b.config
- cabal.project
```

## Ord ProjectConfigPath Instance Changes

For comparison purposes, path separators are normalized to the @buildOS@
platform's path separator.

```haskell
-- >>> let abFwd = ProjectConfigPath $ "a/b.config" :| []
-- >>> let abBwd = ProjectConfigPath $ "a\\b.config" :| []
-- >>> compare abFwd abBwd
-- EQ
```

0 comments on commit 8a5a5b4

Please sign in to comment.