This repository was archived by the owner on Oct 7, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 206
/
Copy pathLiquidSpec.hs
140 lines (118 loc) · 4.78 KB
/
LiquidSpec.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE NamedFieldPuns #-}
module LiquidSpec where
import Data.Aeson
import Data.List
import qualified Data.ByteString.Lazy as BS
import qualified Data.Text as T
import qualified Data.Text.IO as T
#if __GLASGOW_HASKELL__ < 808
import Data.Monoid ((<>))
#endif
import Haskell.Ide.Engine.MonadTypes
import Haskell.Ide.Engine.Plugin.Liquid
import System.Directory
import System.Exit
import System.FilePath
import System.Process
import Test.Hspec
-- import Control.Monad.IO.Class
main :: IO ()
main = hspec spec
spec :: Spec
spec = do
describe "liquid haskell plugin" $ do
cwd <- runIO getCurrentDirectory
-- ---------------------------------
it "the liquid haskell exe in $PATH has the supported version" $ do
mexe <- findExecutable "liquid"
case mexe of
Nothing -> expectationFailure "liquid haskell exe is NOT in $PATH"
Just exe -> do
version <- readProcess exe ["--numeric-version"] ""
version `shouldSatisfy` ("0.8.6" `isPrefixOf`)
-- ---------------------------------
-- This produces some products in /test/testdata/liquid/.liquid/
-- that are used in subsequent test
it "runs the liquid haskell exe" $ do
let
fp = cwd </> "test/testdata/liquid/Evens.hs"
Just (ef, (msg:_)) <- runLiquidHaskell fp
-- liftIO $ putStrLn $ "msg=" ++ msg
-- liftIO $ putStrLn $ "msg=" ++ unlines (drop 3 (lines msg))
let msg' = unlines (drop 3 (lines msg))
msg' `shouldSatisfy` isInfixOf "RESULT\n[{\"start\":{\"line\""
ef `shouldBe` ExitFailure 1
-- ---------------------------------
it "gets annot file paths" $ do
let
uri = filePathToUri $ cwd </> "test/testdata/liquid/Evens.hs"
vimFile = vimAnnotFile uri
jsonFile = jsonAnnotFile uri
vimFile `shouldBe` normalise (cwd </> "test/testdata/liquid/.liquid/Evens.hs.vim.annot")
jsonFile `shouldBe` normalise (cwd </> "test/testdata/liquid/.liquid/Evens.hs.json")
-- ---------------------------------
it "reads errors from json file" $ do
let
uri = filePathToUri $ cwd </> "test/testdata/liquid/Evens.hs"
jsonFile = jsonAnnotFile uri
jf <- BS.readFile jsonFile
let Just v = decode jf :: Maybe LiquidJson
let [LE { start, stop, message }] = errors v
start `shouldBe` LP 9 1
stop `shouldBe` LP 9 12
message `shouldSatisfy` T.isPrefixOf
("Error: Liquid Type Mismatch\n" <>
" Inferred type\n" <>
" VV : {v : GHC.Types.Int | v == 7}\n" <>
" \n" <>
" not a subtype of Required type\n" <>
" VV : {VV : GHC.Types.Int | VV mod 2 == 0}\n" <>
" ")
-- ---------------------------------
it "gracefully manages missing json file" $ do
let
uri = filePathToUri $ cwd </> "test/testdata/Rename.hs"
n <- readJsonAnnot uri
n `shouldBe` Nothing
-- ---------------------------------
it "parses a vim annotation" $ do
parseType "6:1-6:10::Main.weAreEven :: \"[{v : GHC.Types.Int | v mod 2 == 0}]\""
`shouldBe`
[LE (LP 6 1) (LP 6 10) "[{v : GHC.Types.Int | v mod 2 == 0}]"]
-- ---------------------------------
it "parses multiple vim annotations" $ do
parseType "1:1-1:1::Main.$trModule :: \"GHC.Types.Module\"\n6:1-6:10::Main.weAreEven :: \"[{v : GHC.Types.Int | v mod 2 == 0}]\""
`shouldBe`
[LE (LP 1 1) (LP 1 1) "GHC.Types.Module"
,LE (LP 6 1) (LP 6 10) "[{v : GHC.Types.Int | v mod 2 == 0}]"]
-- ---------------------------------
it "reads types from vim.annot file" $ do
let
uri = filePathToUri $ cwd </> "test/testdata/liquid/Evens.hs"
vimFile = vimAnnotFile uri
vf <- T.readFile vimFile
let ts = parseType vf
take 2 ts
`shouldBe`
[LE (LP 1 1) (LP 1 1) "GHC.Types.Module"
,LE (LP 6 1) (LP 6 10) "[{VV : GHC.Types.Int | VV mod 2 == 0}]"]
length ts `shouldBe` 53
-- ---------------------------------
it "reads types from vim.annot file 2" $ do
let
uri = filePathToUri $ cwd </> "test/testdata/liquid/Evens.hs"
Just ts <- readVimAnnot uri
take 2 ts
`shouldBe`
[LE (LP 1 1) (LP 1 1) "GHC.Types.Module"
,LE (LP 6 1) (LP 6 10) "[{VV : GHC.Types.Int | VV mod 2 == 0}]"]
length ts `shouldBe` 53
-- ---------------------------------
it "gracefully manages missing vim.annot file" $ do
let
uri = filePathToUri $ cwd </> "test/testdata/Rename.hs"
n <- readVimAnnot uri
n `shouldBe` Nothing
-- ---------------------------------