1
1
mirror of https://github.com/github/semantic.git synced 2024-12-23 14:54:16 +03:00
semantic/test/IntegrationSpec.hs

142 lines
5.9 KiB
Haskell
Raw Normal View History

2017-03-09 00:56:08 +03:00
{-# LANGUAGE DataKinds, GeneralizedNewtypeDeriving, OverloadedStrings #-}
module IntegrationSpec where
2017-04-03 23:34:25 +03:00
import Command
2017-04-03 19:18:40 +03:00
import Command.Parse
import Data.Functor.Both
2017-04-03 23:34:25 +03:00
import Data.List (union, concat, transpose)
import Data.Record
import qualified Data.Text as T
2017-03-09 00:56:08 +03:00
import qualified Data.ByteString as B
import Data.Text.Encoding (decodeUtf8)
2017-04-03 23:34:25 +03:00
import Diff
import GHC.Show (Show(..))
import Info
2017-04-03 23:34:25 +03:00
import Prologue hiding (fst, snd, readFile)
import Renderer.SExpression as Renderer
import Source
2017-04-03 23:34:25 +03:00
import Syntax
import System.FilePath
import System.FilePath.Glob
import Test.Hspec (Spec, describe, it, SpecWith, runIO, parallel)
import Test.Hspec.Expectations.Pretty
spec :: Spec
spec = parallel $ do
it "lists example fixtures" $ do
2017-02-23 21:06:49 +03:00
examples "test/fixtures/go/" `shouldNotReturn` []
2017-02-23 20:55:30 +03:00
examples "test/fixtures/javascript/" `shouldNotReturn` []
2017-02-24 19:44:50 +03:00
examples "test/fixtures/ruby/" `shouldNotReturn` []
examples "test/fixtures/typescript/" `shouldNotReturn` []
2017-02-23 21:06:49 +03:00
describe "go" $ runTestsIn "test/fixtures/go/"
2017-02-23 20:55:30 +03:00
describe "javascript" $ runTestsIn "test/fixtures/javascript/"
2017-02-23 07:06:05 +03:00
describe "ruby" $ runTestsIn "test/fixtures/ruby/"
describe "typescript" $ runTestsIn "test/fixtures/typescript/"
where
2017-02-22 03:05:08 +03:00
runTestsIn :: FilePath -> SpecWith ()
runTestsIn directory = do
examples <- runIO $ examples directory
2017-02-22 03:30:39 +03:00
traverse_ runTest examples
2017-02-23 07:06:05 +03:00
runTest ParseExample{..} = it ("parses " <> file) $ testParse file parseOutput
2017-04-03 23:34:25 +03:00
runTest DiffExample{..} = it ("diffs " <> diffOutput) $ testDiff (Renderer.sExpression TreeOnly) (both fileA fileB) diffOutput
data Example = DiffExample { fileA :: FilePath, fileB :: FilePath, diffOutput :: FilePath }
| ParseExample { file :: FilePath, parseOutput :: FilePath }
2017-02-22 03:30:39 +03:00
deriving (Eq, Show)
-- | Return all the examples from the given directory. Examples are expected to
2017-02-22 19:32:19 +03:00
-- | have the form:
-- |
2017-02-23 01:07:47 +03:00
-- | example-name.A.rb - The left hand side of the diff.
-- | example-name.B.rb - The right hand side of the diff.
2017-02-22 03:05:08 +03:00
-- |
2017-02-23 01:07:47 +03:00
-- | example-name.diffA-B.txt - The expected sexpression diff output for A -> B.
-- | example-name.diffB-A.txt - The expected sexpression diff output for B -> A.
2017-02-22 03:05:08 +03:00
-- |
2017-02-23 01:07:47 +03:00
-- | example-name.parseA.txt - The expected sexpression parse tree for example-name.A.rb
-- | example-name.parseB.txt - The expected sexpression parse tree for example-name.B.rb
2017-02-22 03:30:39 +03:00
examples :: FilePath -> IO [Example]
examples directory = do
as <- globFor "*.A.*"
bs <- globFor "*.B.*"
sExpAs <- globFor "*.parseA.txt"
sExpBs <- globFor "*.parseB.txt"
sExpDiffsAddA <- globFor "*.diff+A.txt"
sExpDiffsRemoveA <- globFor "*.diff-A.txt"
sExpDiffsAddB <- globFor "*.diff+B.txt"
sExpDiffsRemoveB <- globFor "*.diff-B.txt"
sExpDiffsAB <- globFor "*.diffA-B.txt"
sExpDiffsBA <- globFor "*.diffB-A.txt"
let exampleDiff lefts rights out name = DiffExample (lookupNormalized name lefts) (lookupNormalized name rights) out
let exampleAddDiff files out name = DiffExample "" (lookupNormalized name files) out
let exampleRemoveDiff files out name = DiffExample (lookupNormalized name files) "" out
2017-02-23 01:07:47 +03:00
let exampleParse files out name = ParseExample (lookupNormalized name files) out
let keys = (normalizeName <$> as) `union` (normalizeName <$> bs)
pure $ merge [ getExamples (exampleParse as) sExpAs keys
, getExamples (exampleParse bs) sExpBs keys
, getExamples (exampleAddDiff as) sExpDiffsAddA keys
, getExamples (exampleRemoveDiff as) sExpDiffsRemoveA keys
, getExamples (exampleAddDiff bs) sExpDiffsAddB keys
, getExamples (exampleRemoveDiff bs) sExpDiffsRemoveB keys
, getExamples (exampleDiff as bs) sExpDiffsAB keys
, getExamples (exampleDiff bs as) sExpDiffsBA keys ]
where
merge = concat . transpose
2017-02-23 01:07:47 +03:00
-- Only returns examples if they exist
getExamples f list = foldr (go f list) []
where go f list name acc = case lookupNormalized' name list of
Just out -> f out name : acc
Nothing -> acc
2017-02-22 03:05:08 +03:00
lookupNormalized :: FilePath -> [FilePath] -> FilePath
lookupNormalized name xs = fromMaybe
(panic ("cannot find " <> T.pack name <> " make sure .A, .B and exist." :: Text))
2017-02-23 01:07:47 +03:00
(lookupNormalized' name xs)
lookupNormalized' :: FilePath -> [FilePath] -> Maybe FilePath
lookupNormalized' name = find ((== name) . normalizeName)
globFor :: FilePath -> IO [FilePath]
globFor p = globDir1 (compile p) directory
2017-02-22 03:05:08 +03:00
-- | Given a test name like "foo.A.js", return "foo".
normalizeName :: FilePath -> FilePath
normalizeName path = dropExtension $ dropExtension path
2017-02-22 19:32:19 +03:00
testParse :: FilePath -> FilePath -> Expectation
testParse path expectedOutput = do
source <- readAndTranscodeFile path
let blob = sourceBlob source path
2017-03-29 03:10:35 +03:00
term <- parserForType (toS (takeExtension path)) blob
2017-02-22 19:32:19 +03:00
let actual = (Verbatim . stripWhitespace) $ printTerm term 0 TreeOnly
2017-03-09 00:56:08 +03:00
expected <- (Verbatim . stripWhitespace) <$> B.readFile expectedOutput
2017-02-22 19:32:19 +03:00
actual `shouldBe` expected
2017-04-03 23:34:25 +03:00
testDiff :: (Both SourceBlob -> Diff (Syntax Text) (Record DefaultFields) -> ByteString) -> Both FilePath -> FilePath -> Expectation
2017-03-14 02:25:18 +03:00
testDiff renderer paths expectedOutput = do
2017-04-03 23:34:25 +03:00
(blobs, diff') <- runCommand $ do
2017-04-04 03:09:02 +03:00
blobs <- traverse readFile paths
terms <- traverse (traverse parseBlob) blobs
2017-04-04 17:42:51 +03:00
Just diff' <- maybeDiff terms
return (fromMaybe . emptySourceBlob <$> paths <*> blobs, diff')
2017-04-03 23:34:25 +03:00
let diffOutput = renderer blobs diff'
let actual = Verbatim (stripWhitespace diffOutput)
expected <- Verbatim . stripWhitespace <$> B.readFile expectedOutput
2017-02-22 03:05:08 +03:00
actual `shouldBe` expected
2017-03-09 00:56:08 +03:00
stripWhitespace :: ByteString -> ByteString
stripWhitespace = B.foldl' go B.empty
where go acc x | x `B.elem` " \t\n" = acc
| otherwise = B.snoc acc x
2017-03-09 00:56:08 +03:00
-- | A wrapper around `ByteString` with a more readable `Show` instance.
newtype Verbatim = Verbatim ByteString
deriving (Eq, NFData)
instance Show Verbatim where
2017-03-09 00:56:08 +03:00
showsPrec _ (Verbatim byteString) = ('\n':) . (T.unpack (decodeUtf8 byteString) ++)