weeder-2.9.0: test/Main.hs
module Main (main) where
import qualified Weeder.Main
import qualified Weeder.Run
import qualified Weeder
import qualified TOML
import qualified UnitTests.Weeder.ConfigSpec
import Data.Maybe
import Algebra.Graph.Export.Dot
import GHC.Types.Name.Occurrence (occNameString)
import System.Directory
import System.FilePath
import System.IO (stderr, hPrint)
import Test.Tasty (TestTree, defaultMain, testGroup)
import Control.Exception ( throwIO, IOException, handle )
import Data.List (find, sortOn)
import qualified Data.ByteString.Lazy as LBS
import Data.Text (pack)
import Data.Text.Encoding (encodeUtf8)
import Test.Tasty.Golden
main :: IO ()
main = do
testOutputFiles <- fmap sortTests discoverIntegrationTests
let hieDirectories = map (dropExtension . snd) testOutputFiles
defaultMain $
testGroup "Weeder"
[ testGroup "Weeder.Run" $
[ testGroup "runWeeder" $
zipWith (uncurry integrationTest)
testOutputFiles
hieDirectories
]
, UnitTests.Weeder.ConfigSpec.tests
]
where
-- Sort the output files such that the failing ones go last
sortTests = sortOn (isJust . fst)
-- | Run weeder on @hieDirectory@, comparing the output to @stdoutFile@.
--
-- The directory containing @hieDirectory@ must also have a @.toml@ file
-- with the same name as @hieDirectory@.
--
-- If @failingFile@ is @Just@, it is used as the expected output instead of
-- @stdoutFile@, and a different failure message is printed if the output
-- matches @stdoutFile@.
integrationTest :: Maybe FilePath -> FilePath -> FilePath -> TestTree
integrationTest failingFile stdoutFile hieDirectory = do
goldenVsString (integrationTestText ++ hieDirectory) (fromMaybe stdoutFile failingFile) $
integrationTestOutput hieDirectory
where
integrationTestText = case failingFile of
Nothing -> "produces the expected output for "
Just _ -> "produces the expected (wrong) output for "
-- | Returns detected .failing and .stdout files in ./test/Spec
discoverIntegrationTests :: IO [(Maybe FilePath, FilePath)]
discoverIntegrationTests = do
contents <- listDirectory testPath
let stdoutFiles = map (testPath </>) $
filter (".stdout" `isExtensionOf`) contents
pure . map (\s -> (findFailing s contents, s)) $ stdoutFiles
where
findFailing s = fmap (testPath </>) . find (takeBaseName s <.> ".failing" ==)
testPath = "./test/Spec"
-- | Run weeder on the given directory for .hie files, returning stdout
-- Also creates a dotfile containing the dependency graph as seen by Weeder
integrationTestOutput :: FilePath -> IO LBS.ByteString
integrationTestOutput hieDirectory = do
hieFiles <- Weeder.Main.getHieFiles ".hie" [hieDirectory] False
weederConfig <- TOML.decodeFile configExpr >>= either throwIO pure
let (weeds, analysis) = Weeder.Run.runWeeder weederConfig hieFiles
graph = Weeder.dependencyGraph analysis
graph' = export (defaultStyle (occNameString . Weeder.declOccName)) graph
handle (\e -> hPrint stderr (e :: IOException)) $
writeFile (hieDirectory <.> ".dot") graph'
pure (LBS.fromStrict $ encodeUtf8 $ pack $ unlines $ map Weeder.Run.formatWeed weeds)
where
configExpr = hieDirectory <.> ".toml"