mirror of
https://github.com/reanimate/reanimate.git
synced 2026-09-10 15:42:21 +00:00
setup unit tests for Nix
Both for a `nix-build`, where `cabal` executable is not present, but also just for using Stack with nix integration. With nix integration, Stack will make a `nix-shell` where `stack` executable is not found. We use "bare-bones" GHC to solve this. This GHC doesn't exactly respect our Stack or Cabal configurations, so we need to avoid `cubicbezier`'s `matrices` dependency so that `Data.Matrix` resolves to `matrix` package. Also, we don't error on compiler warnings when compiling test files through Nix. I don't know if these warnings would show up on a regular Stack or Cabal config (I'm on NixOS), so it's unaffected for those. TL;DR: Added testing support for Nix build environments; Cabal and Stack environments should be unchanged.
This commit is contained in:
parent
bae6456026
commit
a9b758ea0a
5 changed files with 137 additions and 16 deletions
|
|
@ -60,6 +60,10 @@ op2LaTeX LeftParen = "("
|
|||
op2LaTeX RightParen = ")"
|
||||
|
||||
-- Some supportive types and instances.
|
||||
instance Functor (Expr a) where
|
||||
fmap f (Var x) = Var (f x)
|
||||
fmap f (BinOp x op y) = BinOp (fmap f x) op (fmap f y)
|
||||
fmap f (Paren l x r) = Paren l (fmap f x) r
|
||||
|
||||
instance Bifunctor Expr where
|
||||
bimap _ g (Var x) = Var (g x)
|
||||
|
|
@ -91,6 +95,9 @@ instance Bitraversable p => Traversable (Both p) where
|
|||
-- | Make a bifunctor @f (a, -) (b, -)@ (namely @BiAlongside a b f@) out of @f@.
|
||||
newtype BiAlongside a b f x y = BiAlongside { runBiAlongside :: f (a, x) (b, y) }
|
||||
|
||||
instance Bifunctor p => Functor (BiAlongside a b p c) where
|
||||
fmap f (BiAlongside x) = BiAlongside (bimap id (fmap f) x)
|
||||
|
||||
instance Bifunctor p => Bifunctor (BiAlongside a b p) where
|
||||
bimap f g = BiAlongside . bimap (second f) (second g) . runBiAlongside
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
module Main (main) where
|
||||
|
||||
import Codec.Picture
|
||||
import Control.Monad (forM_, when, zipWithM_)
|
||||
import Control.Monad.ST
|
||||
import Control.Monad.State.Strict
|
||||
import Data.Text (Text)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
resolver: lts-18.15
|
||||
resolver: lts-24.25
|
||||
|
||||
allow-newer: false
|
||||
|
||||
packages:
|
||||
- .
|
||||
|
||||
extra-deps: []
|
||||
extra-deps:
|
||||
- geojson-4.1.1@sha256:f450e81d4fe1993f97c7cdb2b9743d54d2621c37b67d8a89536e5e09d33fd737,4233
|
||||
- reanimate-svg-0.13.0.1@sha256:260957e61e2e290a6cbca1d129fa0da66d624a224d0016d3bdc76fa210c70cbd,2950
|
||||
|
||||
|
|
|
|||
26
stack.yaml.lock
Normal file
26
stack.yaml.lock
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# This file was autogenerated by Stack.
|
||||
# You should not edit this file by hand.
|
||||
# For more information, please see the documentation at:
|
||||
# https://docs.haskellstack.org/en/stable/topics/lock_files
|
||||
|
||||
packages:
|
||||
- completed:
|
||||
hackage: geojson-4.1.1@sha256:f450e81d4fe1993f97c7cdb2b9743d54d2621c37b67d8a89536e5e09d33fd737,4233
|
||||
pantry-tree:
|
||||
sha256: 0a1c1e2c6533b27efd472de9931e99d5cd05e0db568840e6e6dc014c8a2591cd
|
||||
size: 2376
|
||||
original:
|
||||
hackage: geojson-4.1.1@sha256:f450e81d4fe1993f97c7cdb2b9743d54d2621c37b67d8a89536e5e09d33fd737,4233
|
||||
- completed:
|
||||
hackage: reanimate-svg-0.13.0.1@sha256:260957e61e2e290a6cbca1d129fa0da66d624a224d0016d3bdc76fa210c70cbd,2950
|
||||
pantry-tree:
|
||||
sha256: 93a217570c21431d5c9cf369058c8227aa1dee3a506edfed324550969c55a685
|
||||
size: 39432
|
||||
original:
|
||||
hackage: reanimate-svg-0.13.0.1@sha256:260957e61e2e290a6cbca1d129fa0da66d624a224d0016d3bdc76fa210c70cbd,2950
|
||||
snapshots:
|
||||
- completed:
|
||||
sha256: c0060a2ed91942bd6426f00617125fe9f0fef613dad0acc5f0ea10e8d499f799
|
||||
size: 726335
|
||||
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/24/25.yaml
|
||||
original: lts-24.25
|
||||
|
|
@ -5,9 +5,11 @@ module UnitTests
|
|||
) where
|
||||
|
||||
import Control.Exception
|
||||
import Control.Monad (filterM)
|
||||
import qualified Data.ByteString as BS
|
||||
import qualified Data.ByteString.Lazy as LBS
|
||||
import Data.List (sort)
|
||||
import Data.Maybe (maybe)
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Text.IO as T
|
||||
import System.Directory
|
||||
|
|
@ -23,22 +25,78 @@ import Test.Tasty.HUnit
|
|||
data BuildSystem
|
||||
= Cabal
|
||||
| Stack
|
||||
| NixBuild NixBuildSystem
|
||||
|
||||
data NixBuildSystem
|
||||
= NixCabal
|
||||
| NixStack
|
||||
|
||||
-- required for nix build
|
||||
nixGHCOptions :: [String]
|
||||
nixGHCOptions =
|
||||
[ "-XPackageImports"
|
||||
, "-XPatternSynonyms"
|
||||
, "-Wall"
|
||||
, "-fno-ignore-asserts"
|
||||
, "-DNO_HGEOMETRY"
|
||||
, "-hide-package"
|
||||
, "matrices"
|
||||
]
|
||||
|
||||
findStackAutogen :: IO (Maybe FilePath)
|
||||
findStackAutogen = do
|
||||
let base = ".stack-work" </> "dist"
|
||||
baseExists <- doesDirectoryExist base
|
||||
if not baseExists
|
||||
then return Nothing
|
||||
else do
|
||||
subDirs <- listDirectories base
|
||||
case subDirs of
|
||||
[] -> return Nothing
|
||||
(arch:_) -> do
|
||||
let archPath = base </> arch
|
||||
cabalDirs <- listDirectories archPath
|
||||
case cabalDirs of
|
||||
[] -> return Nothing
|
||||
(ver:_) -> return $ Just (archPath </> ver </> "build" </> "autogen")
|
||||
|
||||
includeBuild :: NixBuildSystem -> IO [String]
|
||||
includeBuild NixCabal = return ["-idist/build/autogen"]
|
||||
includeBuild NixStack = do
|
||||
mbPath <- findStackAutogen
|
||||
case mbPath of
|
||||
Nothing -> return []
|
||||
Just p -> return ["-i" ++ p]
|
||||
|
||||
listDirectories :: FilePath -> IO [FilePath]
|
||||
listDirectories path = do
|
||||
contents <- listDirectory path
|
||||
filterM (\f -> doesDirectoryExist (path </> f)) contents
|
||||
|
||||
{-# NOINLINE buildSystem #-}
|
||||
buildSystem :: BuildSystem
|
||||
buildSystem = unsafePerformIO $ do
|
||||
exeCabal <- findExecutable "cabal"
|
||||
exeStack <- findExecutable "stack"
|
||||
|
||||
newbuild <- doesDirectoryExist "dist-newstyle"
|
||||
stack <- doesDirectoryExist ".stack-work"
|
||||
if newbuild then pure Cabal
|
||||
else if stack then pure Stack
|
||||
else error "Unknown build system."
|
||||
v1build <- doesDirectoryExist "dist"
|
||||
stack <- doesDirectoryExist ".stack-work"
|
||||
|
||||
return $ case (exeCabal, exeStack) of
|
||||
(Nothing, _) | v1build -> NixBuild NixCabal
|
||||
(_, Nothing) | stack -> NixBuild NixStack
|
||||
(Just _, _) | newbuild -> Cabal
|
||||
(_, Just _) | stack -> Stack
|
||||
_ -> error "Unknown build system."
|
||||
|
||||
{-# NOINLINE unitTestsDisabled #-}
|
||||
unitTestsDisabled :: Bool
|
||||
unitTestsDisabled =
|
||||
case buildSystem of
|
||||
Cabal -> False
|
||||
Stack -> unsafePerformIO $ do
|
||||
Cabal -> False
|
||||
NixBuild _ -> False
|
||||
Stack -> unsafePerformIO $ do
|
||||
(ret, _, _) <- readProcessWithExitCode "stack" ["exec","--","ghc", "-e", "Reanimate.duration Reanimate.Builtin.Documentation.drawCircle"] ""
|
||||
case ret of
|
||||
ExitFailure{} -> pure True
|
||||
|
|
@ -64,16 +122,26 @@ unitTestFolder path = do
|
|||
genGolden :: FilePath -> IO LBS.ByteString
|
||||
genGolden path = do
|
||||
(inh, outh, errh, pid) <- case buildSystem of
|
||||
Stack -> runInteractiveProcess "stack" ["runhaskell", path, "test"]
|
||||
Stack -> runInteractiveProcess "stack" ["runhaskell", path, "test"]
|
||||
Nothing Nothing
|
||||
Cabal -> runInteractiveProcess "cabal" ["v2-exec", "runhaskell", path, "test"]
|
||||
Cabal -> runInteractiveProcess "cabal" ["v2-exec", "runhaskell", path, "test"]
|
||||
Nothing Nothing
|
||||
NixBuild nixbuild -> do
|
||||
nixIncludeDir <- includeBuild nixbuild
|
||||
runInteractiveProcess "ghc"
|
||||
( ["-isrc", "-iunix"]
|
||||
++ nixIncludeDir
|
||||
++ nixGHCOptions
|
||||
++ ["--run", path, "--", "test"]
|
||||
) Nothing Nothing
|
||||
-- hSetBinaryMode outh True
|
||||
-- hSetNewlineMode outh universalNewlineMode
|
||||
-- hSetNewlineMode outh universalNewlineMode
|
||||
|
||||
hClose inh
|
||||
out <- BS.hGetContents outh
|
||||
err <- T.hGetContents errh
|
||||
code <- waitForProcess pid
|
||||
|
||||
case code of
|
||||
ExitSuccess -> return $ LBS.fromChunks [out]
|
||||
ExitFailure{} -> error $ "Failed to run: " ++ T.unpack err
|
||||
|
|
@ -87,9 +155,17 @@ compileTestFolder path = do
|
|||
[ testCase file $ do
|
||||
(ret, _stdout, err) <-
|
||||
case buildSystem of
|
||||
Stack -> readProcessWithExitCode "stack" (["ghc","--", fullPath] ++ ghcOpts) ""
|
||||
Cabal -> readProcessWithExitCode "cabal"
|
||||
Stack -> readProcessWithExitCode "stack" (["ghc","--", fullPath] ++ ghcOpts) ""
|
||||
Cabal -> readProcessWithExitCode "cabal"
|
||||
(["v2-exec","ghc","--", "-package", "reanimate", fullPath] ++ ghcOpts) ""
|
||||
NixBuild nixbuild -> do
|
||||
nixIncludeDir <- includeBuild nixbuild
|
||||
readProcessWithExitCode "ghc"
|
||||
( ["-isrc", "-iunix"]
|
||||
++ nixIncludeDir
|
||||
++ nixGHCOptions
|
||||
++ [fullPath] ++ (init ghcOpts)
|
||||
) ""
|
||||
_ <- evaluate (length err)
|
||||
case ret of
|
||||
ExitFailure{} -> assertFailure $ "Failed to compile:\n" ++ err
|
||||
|
|
@ -100,7 +176,7 @@ compileTestFolder path = do
|
|||
, notElem (replaceExtension file "golden") goldenFiles
|
||||
]
|
||||
where
|
||||
ghcOpts = ["-fno-code", "-O0", "-Werror", "-Wall"]
|
||||
ghcOpts = ["-fno-code", "-O0", "-Wall", "-Werror"]
|
||||
|
||||
compileVideoFolder :: FilePath -> IO TestTree
|
||||
compileVideoFolder _ | unitTestsDisabled = return $ testGroup "videos (disabled)" []
|
||||
|
|
@ -113,8 +189,16 @@ compileVideoFolder path = do
|
|||
[ testCase dir $ do
|
||||
(ret, _stdout, err) <-
|
||||
case buildSystem of
|
||||
Stack -> readProcessWithExitCode "stack" (["ghc","--", "-i"++path</>dir, fullPath] ++ ghcOpts) ""
|
||||
Cabal -> readProcessWithExitCode "cabal" (["v2-exec", "ghc","--", "-package", "reanimate", "-i"++path</>dir, fullPath] ++ ghcOpts) ""
|
||||
Stack -> readProcessWithExitCode "stack" (["ghc","--", "-i"++path</>dir, fullPath] ++ ghcOpts) ""
|
||||
Cabal -> readProcessWithExitCode "cabal" (["v2-exec", "ghc","--", "-package", "reanimate", "-i"++path</>dir, fullPath] ++ ghcOpts) ""
|
||||
NixBuild nixbuild -> do
|
||||
nixIncludeDir <- includeBuild nixbuild
|
||||
readProcessWithExitCode "ghc"
|
||||
( ["-isrc", "-iunix", "-i"++path</>dir]
|
||||
++ nixIncludeDir
|
||||
++ nixGHCOptions
|
||||
++ [fullPath] ++ ghcOpts
|
||||
) ""
|
||||
_ <- evaluate (length err)
|
||||
case ret of
|
||||
ExitFailure{} -> assertFailure $ "Failed to compile:\n" ++ err
|
||||
|
|
|
|||
Loading…
Reference in a new issue