1
1
mirror of https://github.com/github/semantic.git synced 2024-12-21 05:41:54 +03:00
semantic/test/CorpusSpec.hs

101 lines
4.7 KiB
Haskell
Raw Normal View History

{-# LANGUAGE DataKinds, FlexibleContexts, GeneralizedNewtypeDeriving #-}
2016-02-16 20:33:41 +03:00
module CorpusSpec where
import Category
2016-02-18 01:42:27 +03:00
import Control.DeepSeq
import Data.Functor.Both
2016-08-09 22:51:01 +03:00
import Data.List (union)
import Data.Record
2016-02-17 23:54:37 +03:00
import qualified Data.Text as T
import qualified Data.Vector as Vector
import Diffing
import GHC.Show (Show(..))
import Info
2016-08-09 22:51:01 +03:00
import Prologue hiding (fst, snd, lookup)
import Renderer
import qualified Renderer.JSON as J
import qualified Renderer.Patch as P
import qualified Renderer.Split as Split
2016-03-01 03:39:04 +03:00
import qualified Source as S
2016-02-17 00:38:31 +03:00
import System.FilePath
import System.FilePath.Glob
2016-02-16 20:33:41 +03:00
import Test.Hspec
import Unsafe (unsafeFromJust)
2016-02-16 20:33:41 +03:00
spec :: Spec
2016-02-18 01:43:59 +03:00
spec = parallel $ do
describe "crashers crash" . runTestsIn "test/crashers-todo/" $ \ a b ->
a `deepseq` pure (a == b) `shouldThrow` anyException
2016-02-29 06:18:44 +03:00
describe "crashers should not crash" $ runTestsIn "test/crashers/" shouldBe
describe "todos are incorrect" $ runTestsIn "test/diffs-todo/" shouldNotBe
describe "should produce the correct diff" $ runTestsIn "test/diffs/" shouldBe
2016-02-17 00:38:31 +03:00
2016-02-17 20:54:42 +03:00
it "lists example fixtures" $ do
2016-02-17 00:38:31 +03:00
examples "test/crashers/" `shouldNotReturn` []
2016-02-17 20:54:42 +03:00
examples "test/diffs/" `shouldNotReturn` []
2016-02-17 00:38:31 +03:00
where
2016-08-09 22:51:01 +03:00
runTestsIn :: FilePath -> (Maybe Verbatim -> Maybe Verbatim -> Expectation) -> SpecWith ()
2016-02-22 22:38:49 +03:00
runTestsIn directory matcher = do
2016-02-18 01:10:04 +03:00
paths <- runIO $ examples directory
let tests = correctTests =<< paths
2016-08-09 22:51:01 +03:00
traverse_ (\ (formatName, renderer, paths, output) ->
2016-08-10 18:00:40 +03:00
it (maybe "/dev/null" normalizeName (uncurry (<|>) (runJoin paths)) ++ " (" ++ formatName ++ ")") $ testDiff renderer paths output matcher) tests
2016-02-17 00:38:31 +03:00
2016-08-09 22:51:01 +03:00
correctTests paths@(_, _, Nothing, Nothing, Nothing) = testsForPaths paths
correctTests paths = filter (\(_, _, _, output) -> isJust output) $ testsForPaths paths
testsForPaths (aPath, bPath, json, patch, split) = [ ("json", J.json, paths, json), ("patch", P.patch, paths, patch), ("split", Split.split, paths, split) ]
where paths = both aPath bPath
2016-02-17 00:38:31 +03:00
-- | Return all the examples from the given directory. Examples are expected to
2016-02-27 03:04:47 +03:00
-- | have the form "foo.A.js", "foo.B.js", "foo.patch.js". Diffs are not
2016-02-17 00:38:31 +03:00
-- | required as the test may be verifying that the inputs don't crash.
2016-08-09 22:51:01 +03:00
examples :: FilePath -> IO [(Maybe FilePath, Maybe FilePath, Maybe FilePath, Maybe FilePath, Maybe FilePath)]
2016-02-17 00:38:31 +03:00
examples directory = do
2016-08-09 22:51:01 +03:00
as <- globFor "*.A.*"
bs <- globFor "*.B.*"
jsons <- globFor "*.json.*"
patches <- globFor "*.patch.*"
splits <- globFor "*.split.*"
let lookupName name = (lookupNormalized name as, lookupNormalized name bs, lookupNormalized name jsons, lookupNormalized name patches, lookupNormalized name splits)
2016-08-10 17:58:41 +03:00
let keys = (normalizeName <$> as) `union` (normalizeName <$> bs)
2016-08-09 22:51:01 +03:00
pure $ lookupName <$> keys
2016-02-17 00:38:31 +03:00
where
2016-08-09 22:51:01 +03:00
lookupNormalized name = find $ (== name) . normalizeName
2016-05-30 19:38:21 +03:00
globFor :: FilePath -> IO [FilePath]
2016-02-17 00:38:31 +03:00
globFor p = globDir1 (compile p) directory
-- | Given a test name like "foo.A.js", return "foo.js".
normalizeName :: FilePath -> FilePath
normalizeName path = addExtension (dropExtension $ dropExtension path) (takeExtension path)
-- | Given file paths for A, B, and, optionally, a diff, return whether diffing
-- | the files will produce the diff. If no diff is provided, then the result
-- | is true, but the diff will still be calculated.
testDiff :: Renderer (Record '[Vector.Vector Double, Cost, Range, Category]) -> Both (Maybe FilePath) -> Maybe FilePath -> (Maybe Verbatim -> Maybe Verbatim -> Expectation) -> Expectation
testDiff renderer paths diff matcher = do
2016-08-09 22:51:01 +03:00
sources <- traverse (traverse readAndTranscodeFile) paths
actual <- fmap Verbatim <$> traverse ((pure . concatOutputs . pure) <=< diffFiles' sources) parser
2016-02-17 00:38:31 +03:00
case diff of
Nothing -> matcher actual actual
2016-02-17 00:38:31 +03:00
Just file -> do
expected <- Verbatim <$> readFile file
2016-08-09 22:51:01 +03:00
matcher actual (Just expected)
where diffFiles' sources parser = diffFiles parser renderer (sourceBlobs sources paths)
parser = parserForFilepath <$> runBothWith (<|>) paths
sourceBlobs :: Both (Maybe (S.Source Char)) -> Both (Maybe FilePath) -> Both S.SourceBlob
sourceBlobs sources paths = case runJoin paths of
(Nothing, Nothing) -> Join (S.emptySourceBlob "", S.emptySourceBlob "")
(Nothing, Just filepath) -> Join (S.emptySourceBlob "", S.sourceBlob (unsafeFromJust $ snd sources) filepath)
(Just filepath, Nothing) -> Join (S.sourceBlob (unsafeFromJust $ fst sources) filepath, S.emptySourceBlob "")
(Just path1, Just path2) -> Join (S.sourceBlob (unsafeFromJust $ fst sources) path1, S.sourceBlob (unsafeFromJust $ snd sources) path2)
2016-05-30 19:46:25 +03:00
-- | A wrapper around `Text` with a more readable `Show` instance.
2016-05-30 19:39:43 +03:00
newtype Verbatim = Verbatim Text
deriving (Eq, NFData)
instance Show Verbatim where
showsPrec _ (Verbatim text) = ('\n':) . (T.unpack text ++)