packages feed

weeder-2.6.0: test/Spec.hs

import qualified Weeder.Main
import qualified Weeder
import qualified TOML

import Algebra.Graph.Export.Dot
import GHC.Types.Name.Occurrence (occNameString)
import System.Directory
import System.Environment (getArgs, withArgs)
import System.FilePath
import System.Process
import System.IO.Silently (hCapture_)
import System.IO (stdout, stderr, hPrint)
import Test.Hspec
import Control.Monad (zipWithM_, when)
import Control.Exception ( throwIO, IOException, handle )

main :: IO ()
main = do
  args <- getArgs
  stdoutFiles <- discoverIntegrationTests
  let hieDirectories = map dropExtension stdoutFiles
      drawDots = mapM_ (drawDot . (<.> ".dot")) hieDirectories
      graphviz = "--graphviz" `elem` args
  withArgs (filter (/="--graphviz") args) $
    hspec $ afterAll_ (when graphviz drawDots) $ do
      describe "Weeder.Main" $
        describe "mainWithConfig" $
          zipWithM_ integrationTestSpec stdoutFiles hieDirectories
  where
    -- Draw a dotfile via graphviz
    drawDot f = callCommand $ "dot -Tpng " ++ f ++ " -o " ++ (f -<.> ".png")

-- | 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
integrationTestSpec :: FilePath -> FilePath -> Spec
integrationTestSpec stdoutFile hieDirectory = do
  it ("produces the expected output for " ++ hieDirectory) $ do
    expectedOutput <- readFile stdoutFile
    actualOutput <- integrationTestOutput hieDirectory
    actualOutput `shouldBe` expectedOutput

-- | Returns detected .stdout files in ./test/Spec
discoverIntegrationTests :: IO [FilePath]
discoverIntegrationTests = do
  contents <- listDirectory "./test/Spec"
  pure . map ("./test/Spec" </>) $ filter (".stdout" `isExtensionOf`) contents

-- | 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 String
integrationTestOutput hieDirectory = hCapture_ [stdout] $ do
  isEmpty <- not . any (".hie" `isExtensionOf`) <$> listDirectory hieDirectory
  when isEmpty $ fail "No .hie files found in directory, this is probably unintended"
  (_, analysis) <-
    TOML.decodeFile configExpr
      >>= either throwIO pure
      >>= Weeder.Main.mainWithConfig ".hie" [hieDirectory] True
  let graph = Weeder.dependencyGraph analysis
      graph' = export (defaultStyle (occNameString . Weeder.declOccName)) graph
  handle (\e -> hPrint stderr (e :: IOException)) $
    writeFile (hieDirectory <.> ".dot") graph'
  where
    configExpr = hieDirectory <.> ".toml"