2019-09-30 20:08:09 +03:00
|
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
|
|
|
2018-03-09 20:07:34 +03:00
|
|
|
module Semantic.IO.Spec (spec) where
|
2017-03-01 01:55:57 +03:00
|
|
|
|
2017-07-28 21:37:02 +03:00
|
|
|
import Prelude hiding (readFile)
|
2018-05-23 00:01:17 +03:00
|
|
|
|
2019-09-30 20:08:09 +03:00
|
|
|
import Control.Monad.IO.Class
|
|
|
|
import Data.List
|
|
|
|
import Data.String
|
|
|
|
import qualified Data.Text as Text
|
|
|
|
import System.Directory
|
|
|
|
import System.IO.Temp
|
2018-05-22 23:53:03 +03:00
|
|
|
|
2019-09-30 20:08:09 +03:00
|
|
|
import Data.Blob
|
|
|
|
import Data.Handle
|
2019-05-28 20:24:03 +03:00
|
|
|
import qualified Semantic.Git as Git
|
2019-09-30 20:08:09 +03:00
|
|
|
import Shelly (cd, run_, shelly, silently, touchfile, writefile)
|
2019-10-04 22:49:30 +03:00
|
|
|
import qualified Source.Source as Source
|
2019-10-02 23:53:16 +03:00
|
|
|
import SpecHelpers
|
2019-09-30 20:08:09 +03:00
|
|
|
import System.Path ((</>))
|
2019-09-20 19:26:49 +03:00
|
|
|
import qualified System.Path as Path
|
2017-03-01 01:55:57 +03:00
|
|
|
|
2019-09-29 20:44:14 +03:00
|
|
|
|
|
|
|
makeGitRepo :: FilePath -> IO ()
|
|
|
|
makeGitRepo dir = shelly . silently $ do
|
|
|
|
cd (fromString dir)
|
|
|
|
let git = run_ "git"
|
|
|
|
git ["init"]
|
2019-09-30 20:08:09 +03:00
|
|
|
touchfile "bar.py"
|
|
|
|
writefile "日本語.rb" "# coding: utf-8\n日本語 = 'hello'"
|
|
|
|
git ["add", "日本語.rb", "bar.py"]
|
2019-09-29 20:44:14 +03:00
|
|
|
git ["config", "user.name", "'Test'"]
|
|
|
|
git ["config", "user.email", "'test@test.test'"]
|
|
|
|
git ["commit", "-am", "'test commit'"]
|
|
|
|
|
2017-03-01 01:55:57 +03:00
|
|
|
spec :: Spec
|
2019-06-20 00:22:09 +03:00
|
|
|
spec = do
|
2019-09-30 20:08:09 +03:00
|
|
|
describe "catFile" $ do
|
|
|
|
hasGit <- runIO $ isJust <$> findExecutable "git"
|
|
|
|
when hasGit . it "should not corrupt the output of files with UTF-8 identifiers" $ do
|
|
|
|
result <- liftIO . withSystemTempDirectory "semantic-temp-git-repo" $ \dir -> do
|
|
|
|
makeGitRepo dir
|
|
|
|
trees <- Git.lsTree (dir <> "/.git") (Git.OID "HEAD")
|
|
|
|
Just it <- pure $ find (\p -> "日本語" `isInfixOf` Git.treeEntryPath p) trees
|
|
|
|
Git.catFile (dir <> "/.git") (Git.treeEntryOid it)
|
2019-10-04 22:49:30 +03:00
|
|
|
Source.toText result `shouldSatisfy` ("日本語" `Text.isInfixOf`)
|
2019-09-30 20:08:09 +03:00
|
|
|
|
2019-09-29 20:44:14 +03:00
|
|
|
describe "lsTree" $ do
|
|
|
|
hasGit <- runIO $ isJust <$> findExecutable "git"
|
|
|
|
when hasGit . it "should read all tree entries from a repo" $ do
|
|
|
|
items <- liftIO . withSystemTempDirectory "semantic-temp-git-repo" $ \dir -> do
|
|
|
|
makeGitRepo dir
|
|
|
|
Git.lsTree dir (Git.OID "HEAD")
|
|
|
|
|
|
|
|
length items `shouldBe` 2
|
|
|
|
|
2019-05-28 20:24:03 +03:00
|
|
|
describe "readBlobsFromGitRepo" $ do
|
|
|
|
hasGit <- runIO $ isJust <$> findExecutable "git"
|
|
|
|
when hasGit . it "should read from a git directory" $ do
|
|
|
|
-- This temporary directory will be cleaned after use.
|
|
|
|
blobs <- liftIO . withSystemTempDirectory "semantic-temp-git-repo" $ \dir -> do
|
2019-09-29 20:44:14 +03:00
|
|
|
makeGitRepo dir
|
2019-09-20 19:26:49 +03:00
|
|
|
readBlobsFromGitRepoPath (Path.absDir dir </> Path.relDir ".git") (Git.OID "HEAD") [] []
|
2019-05-28 20:24:03 +03:00
|
|
|
let files = sortOn fileLanguage (blobFile <$> blobs)
|
2019-09-30 20:08:09 +03:00
|
|
|
files `shouldBe` [ File "bar.py" Python
|
|
|
|
, File "日本語.rb" Ruby
|
2019-05-28 20:24:03 +03:00
|
|
|
]
|
|
|
|
|
2019-07-31 03:34:35 +03:00
|
|
|
when hasGit . it "should read from a git directory with --only" $ do
|
|
|
|
-- This temporary directory will be cleaned after use.
|
|
|
|
blobs <- liftIO . withSystemTempDirectory "semantic-temp-git-repo" $ \dir -> do
|
2019-09-20 19:26:49 +03:00
|
|
|
let pdir = Path.absDir dir
|
2019-09-29 20:44:14 +03:00
|
|
|
makeGitRepo dir
|
2019-09-30 20:08:09 +03:00
|
|
|
readBlobsFromGitRepoPath (pdir </> Path.relDir ".git") (Git.OID "HEAD") [] [Path.relFile "日本語.rb"]
|
2019-07-31 03:34:35 +03:00
|
|
|
let files = sortOn fileLanguage (blobFile <$> blobs)
|
2019-09-30 20:08:09 +03:00
|
|
|
files `shouldBe` [ File "日本語.rb" Ruby ]
|
2019-07-31 03:34:35 +03:00
|
|
|
|
|
|
|
when hasGit . it "should read from a git directory with --exclude" $ do
|
|
|
|
-- This temporary directory will be cleaned after use.
|
|
|
|
blobs <- liftIO . withSystemTempDirectory "semantic-temp-git-repo" $ \dir -> do
|
2019-09-29 20:44:14 +03:00
|
|
|
makeGitRepo dir
|
2019-07-31 03:34:35 +03:00
|
|
|
|
2019-09-30 20:08:09 +03:00
|
|
|
readBlobsFromGitRepoPath (Path.absDir dir </> Path.relDir ".git") (Git.OID "HEAD") [Path.relFile "日本語.rb"] []
|
2019-07-31 03:34:35 +03:00
|
|
|
let files = sortOn fileLanguage (blobFile <$> blobs)
|
2019-09-30 20:08:09 +03:00
|
|
|
files `shouldBe` [ File "bar.py" Python ]
|
2019-07-31 03:34:35 +03:00
|
|
|
|
2017-04-21 01:13:28 +03:00
|
|
|
describe "readFile" $ do
|
|
|
|
it "returns a blob for extant files" $ do
|
2018-10-23 22:28:21 +03:00
|
|
|
Just blob <- readBlobFromFile (File "semantic.cabal" Unknown)
|
2018-02-26 21:16:56 +03:00
|
|
|
blobPath blob `shouldBe` "semantic.cabal"
|
2017-04-21 01:13:28 +03:00
|
|
|
|
2017-12-11 21:51:52 +03:00
|
|
|
it "throws for absent files" $ do
|
2018-10-23 22:28:21 +03:00
|
|
|
readBlobFromFile (File "this file should not exist" Unknown) `shouldThrow` anyIOException
|
2017-04-21 01:13:28 +03:00
|
|
|
|
2017-05-17 22:53:05 +03:00
|
|
|
describe "readBlobPairsFromHandle" $ do
|
2018-06-05 01:26:47 +03:00
|
|
|
let a = sourceBlob "method.rb" Ruby "def foo; end"
|
|
|
|
let b = sourceBlob "method.rb" Ruby "def bar(x); end"
|
2017-05-17 22:47:45 +03:00
|
|
|
it "returns blobs for valid JSON encoded diff input" $ do
|
2018-04-18 23:55:21 +03:00
|
|
|
blobs <- blobsFromFilePath "test/fixtures/cli/diff.json"
|
2019-10-18 18:57:26 +03:00
|
|
|
blobs `shouldBe` [Compare a b]
|
2017-05-17 22:47:45 +03:00
|
|
|
|
2017-05-23 21:00:20 +03:00
|
|
|
it "returns blobs when there's no before" $ do
|
2018-04-18 23:55:21 +03:00
|
|
|
blobs <- blobsFromFilePath "test/fixtures/cli/diff-no-before.json"
|
2019-10-18 18:57:26 +03:00
|
|
|
blobs `shouldBe` [Insert b]
|
2017-05-23 21:00:20 +03:00
|
|
|
|
|
|
|
it "returns blobs when there's null before" $ do
|
2018-04-18 23:55:21 +03:00
|
|
|
blobs <- blobsFromFilePath "test/fixtures/cli/diff-null-before.json"
|
2019-10-18 18:57:26 +03:00
|
|
|
blobs `shouldBe` [Insert b]
|
2017-05-23 21:00:20 +03:00
|
|
|
|
|
|
|
it "returns blobs when there's no after" $ do
|
2018-04-18 23:55:21 +03:00
|
|
|
blobs <- blobsFromFilePath "test/fixtures/cli/diff-no-after.json"
|
2019-10-18 18:57:26 +03:00
|
|
|
blobs `shouldBe` [Delete a]
|
2017-05-23 21:00:20 +03:00
|
|
|
|
|
|
|
it "returns blobs when there's null after" $ do
|
2018-04-18 23:55:21 +03:00
|
|
|
blobs <- blobsFromFilePath "test/fixtures/cli/diff-null-after.json"
|
2019-10-18 18:57:26 +03:00
|
|
|
blobs `shouldBe` [Delete a]
|
2017-05-23 21:00:20 +03:00
|
|
|
|
|
|
|
|
2017-05-19 00:04:44 +03:00
|
|
|
it "returns blobs for unsupported language" $ do
|
2018-05-14 17:23:29 +03:00
|
|
|
h <- openFileForReading "test/fixtures/cli/diff-unsupported-language.json"
|
2017-06-15 17:17:41 +03:00
|
|
|
blobs <- readBlobPairsFromHandle h
|
2018-06-05 01:26:47 +03:00
|
|
|
let b' = sourceBlob "test.kt" Unknown "fun main(args: Array<String>) {\nprintln(\"hi\")\n}\n"
|
2019-10-18 18:57:26 +03:00
|
|
|
blobs `shouldBe` [Insert b']
|
2017-05-19 00:04:44 +03:00
|
|
|
|
|
|
|
it "detects language based on filepath for empty language" $ do
|
2018-04-18 23:55:21 +03:00
|
|
|
blobs <- blobsFromFilePath "test/fixtures/cli/diff-empty-language.json"
|
2019-10-18 18:57:26 +03:00
|
|
|
blobs `shouldBe` [Compare a b]
|
2017-05-19 00:04:44 +03:00
|
|
|
|
|
|
|
it "throws on blank input" $ do
|
2018-05-14 17:23:29 +03:00
|
|
|
h <- openFileForReading "test/fixtures/cli/blank.json"
|
2019-06-20 00:14:52 +03:00
|
|
|
readBlobPairsFromHandle h `shouldThrow` jsonException
|
2017-05-17 22:47:45 +03:00
|
|
|
|
2017-05-19 00:04:44 +03:00
|
|
|
it "throws if language field not given" $ do
|
2018-05-14 17:23:29 +03:00
|
|
|
h <- openFileForReading "test/fixtures/cli/diff-no-language.json"
|
2019-06-20 00:14:52 +03:00
|
|
|
readBlobsFromHandle h `shouldThrow` jsonException
|
2017-05-19 00:04:44 +03:00
|
|
|
|
2017-12-11 23:59:14 +03:00
|
|
|
it "throws if null on before and after" $ do
|
2018-05-14 17:23:29 +03:00
|
|
|
h <- openFileForReading "test/fixtures/cli/diff-null-both-sides.json"
|
2019-06-20 00:14:52 +03:00
|
|
|
readBlobPairsFromHandle h `shouldThrow` jsonException
|
2017-12-11 23:59:14 +03:00
|
|
|
|
2017-05-17 23:34:09 +03:00
|
|
|
describe "readBlobsFromHandle" $ do
|
|
|
|
it "returns blobs for valid JSON encoded parse input" $ do
|
2018-05-14 17:23:29 +03:00
|
|
|
h <- openFileForReading "test/fixtures/cli/parse.json"
|
2017-06-15 17:17:41 +03:00
|
|
|
blobs <- readBlobsFromHandle h
|
2018-06-05 01:26:47 +03:00
|
|
|
let a = sourceBlob "method.rb" Ruby "def foo; end"
|
2017-05-17 23:34:09 +03:00
|
|
|
blobs `shouldBe` [a]
|
|
|
|
|
2017-05-19 00:04:44 +03:00
|
|
|
it "throws on blank input" $ do
|
2018-05-14 17:23:29 +03:00
|
|
|
h <- openFileForReading "test/fixtures/cli/blank.json"
|
2019-06-20 00:14:52 +03:00
|
|
|
readBlobsFromHandle h `shouldThrow` jsonException
|
2017-05-17 23:34:09 +03:00
|
|
|
|
2017-06-15 06:20:12 +03:00
|
|
|
where blobsFromFilePath path = do
|
2018-05-14 17:23:29 +03:00
|
|
|
h <- openFileForReading path
|
2017-06-15 17:17:41 +03:00
|
|
|
blobs <- readBlobPairsFromHandle h
|
2017-05-23 21:00:20 +03:00
|
|
|
pure blobs
|
2019-06-20 00:14:52 +03:00
|
|
|
|
|
|
|
jsonException :: Selector InvalidJSONException
|
|
|
|
jsonException = const True
|