Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
gargantext-ihaskell
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gargantext
gargantext-ihaskell
Commits
db351598
Commit
db351598
authored
Jun 09, 2016
by
Andrew Gibiansky
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Clean up test suite by splitting it into pieces
parent
4dc416c2
Changes
6
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
647 additions
and
602 deletions
+647
-602
ihaskell.cabal
ihaskell.cabal
+5
-0
Hspec.hs
src/tests/Hspec.hs
+8
-602
Completion.hs
src/tests/IHaskell/Test/Completion.hs
+220
-0
Eval.hs
src/tests/IHaskell/Test/Eval.hs
+153
-0
Parser.hs
src/tests/IHaskell/Test/Parser.hs
+225
-0
Util.hs
src/tests/IHaskell/Test/Util.hs
+36
-0
No files found.
ihaskell.cabal
View file @
db351598
...
@@ -164,6 +164,11 @@ Test-Suite hspec
...
@@ -164,6 +164,11 @@ Test-Suite hspec
Ghc-Options: -threaded
Ghc-Options: -threaded
Main-Is: Hspec.hs
Main-Is: Hspec.hs
hs-source-dirs: src/tests
hs-source-dirs: src/tests
other-modules:
IHaskell.Test.Eval
IHaskell.Test.Completion
IHaskell.Test.Util
IHaskell.Test.Parser
default-language: Haskell2010
default-language: Haskell2010
build-depends:
build-depends:
base,
base,
...
...
src/tests/Hspec.hs
View file @
db351598
This diff is collapsed.
Click to expand it.
src/tests/IHaskell/Test/Completion.hs
0 → 100644
View file @
db351598
module
IHaskell.Test.Completion
(
testCompletions
)
where
import
Prelude
import
Data.List
(
elemIndex
)
import
qualified
Data.Text
as
T
import
Control.Monad.IO.Class
(
liftIO
)
import
System.Environment
(
setEnv
)
import
System.Directory
(
setCurrentDirectory
,
getCurrentDirectory
)
import
GHC
(
getSessionDynFlags
,
setSessionDynFlags
,
DynFlags
(
..
),
GhcLink
(
..
),
setContext
,
parseImportDecl
,
HscTarget
(
..
),
InteractiveImport
(
..
))
import
Test.Hspec
import
Shelly
(
toTextIgnore
,
(
</>
),
shelly
,
fromText
,
get_env_text
,
FilePath
,
cd
,
mkdir_p
,
touchfile
,
withTmpDir
)
import
IHaskell.Eval.Evaluate
(
Interpreter
,
liftIO
)
import
IHaskell.Eval.Completion
(
complete
,
CompletionType
(
..
),
completionType
,
completionTarget
)
import
IHaskell.Test.Util
(
replace
,
shouldBeAmong
,
ghc
)
-- | @readCompletePrompt "xs*ys"@ return @(xs, i)@ where i is the location of
-- @'*'@ in the input string.
readCompletePrompt
::
String
->
(
String
,
Int
)
readCompletePrompt
string
=
case
elemIndex
'*'
string
of
Nothing
->
error
"Expected cursor written as '*'."
Just
idx
->
(
replace
"*"
""
string
,
idx
)
completionEvent
::
String
->
Interpreter
(
String
,
[
String
])
completionEvent
string
=
complete
newString
cursorloc
where
(
newString
,
cursorloc
)
=
case
elemIndex
'*'
string
of
Nothing
->
error
"Expected cursor written as '*'."
Just
idx
->
(
replace
"*"
""
string
,
idx
)
completionEventInDirectory
::
String
->
IO
(
String
,
[
String
])
completionEventInDirectory
string
=
withHsDirectory
$
const
$
completionEvent
string
shouldHaveCompletionsInDirectory
::
String
->
[
String
]
->
IO
()
shouldHaveCompletionsInDirectory
string
expected
=
do
(
matched
,
completions
)
<-
completionEventInDirectory
string
let
existsInCompletion
=
(`
elem
`
completions
)
unmatched
=
filter
(
not
.
existsInCompletion
)
expected
expected
`
shouldBeAmong
`
completions
completionHas
string
expected
=
do
(
matched
,
completions
)
<-
ghc
$
do
initCompleter
completionEvent
string
let
existsInCompletion
=
(`
elem
`
completions
)
unmatched
=
filter
(
not
.
existsInCompletion
)
expected
expected
`
shouldBeAmong
`
completions
initCompleter
::
Interpreter
()
initCompleter
=
do
flags
<-
getSessionDynFlags
setSessionDynFlags
$
flags
{
hscTarget
=
HscInterpreted
,
ghcLink
=
LinkInMemory
}
-- Import modules.
imports
<-
mapM
parseImportDecl
[
"import Prelude"
,
"import qualified Control.Monad"
,
"import qualified Data.List as List"
,
"import IHaskell.Display"
,
"import Data.Maybe as Maybe"
]
setContext
$
map
IIDecl
imports
completes
::
String
->
[
String
]
->
IO
()
completes
string
expected
=
completionTarget
newString
cursorloc
`
shouldBe
`
expected
where
(
newString
,
cursorloc
)
=
readCompletePrompt
string
testCompletions
::
Spec
testCompletions
=
do
testIdentifierCompletion
testCommandCompletion
testIdentifierCompletion
::
Spec
testIdentifierCompletion
=
describe
"Completion"
$
do
it
"correctly gets the completion identifier without dots"
$
do
"hello*"
`
completes
`
[
"hello"
]
"hello aa*bb goodbye"
`
completes
`
[
"aa"
]
"hello aabb* goodbye"
`
completes
`
[
"aabb"
]
"aacc* goodbye"
`
completes
`
[
"aacc"
]
"hello *aabb goodbye"
`
completes
`
[]
"*aabb goodbye"
`
completes
`
[]
it
"correctly gets the completion identifier with dots"
$
do
"hello test.aa*bb goodbye"
`
completes
`
[
"test"
,
"aa"
]
"Test.*"
`
completes
`
[
"Test"
,
""
]
"Test.Thing*"
`
completes
`
[
"Test"
,
"Thing"
]
"Test.Thing.*"
`
completes
`
[
"Test"
,
"Thing"
,
""
]
"Test.Thing.*nope"
`
completes
`
[
"Test"
,
"Thing"
,
""
]
it
"correctly gets the completion type"
$
do
completionType
"import Data."
12
[
"Data"
,
""
]
`
shouldBe
`
ModuleName
"Data"
""
completionType
"import Prel"
11
[
"Prel"
]
`
shouldBe
`
ModuleName
""
"Prel"
completionType
"import D.B.M"
12
[
"D"
,
"B"
,
"M"
]
`
shouldBe
`
ModuleName
"D.B"
"M"
completionType
" import A."
10
[
"A"
,
""
]
`
shouldBe
`
ModuleName
"A"
""
completionType
"import a.x"
10
[
"a"
,
"x"
]
`
shouldBe
`
Identifier
"x"
completionType
"A.x"
3
[
"A"
,
"x"
]
`
shouldBe
`
Qualified
"A"
"x"
completionType
"a.x"
3
[
"a"
,
"x"
]
`
shouldBe
`
Identifier
"x"
completionType
"pri"
3
[
"pri"
]
`
shouldBe
`
Identifier
"pri"
completionType
":load A"
7
[
"A"
]
`
shouldBe
`
HsFilePath
":load A"
"A"
completionType
":! cd "
6
[
""
]
`
shouldBe
`
FilePath
":! cd "
""
it
"properly completes identifiers"
$
do
"pri*"
`
completionHas
`
[
"print"
]
"ma*"
`
completionHas
`
[
"map"
]
"hello ma*"
`
completionHas
`
[
"map"
]
"print $ catMa*"
`
completionHas
`
[
"catMaybes"
]
it
"properly completes qualified identifiers"
$
do
"Control.Monad.liftM*"
`
completionHas
`
[
"Control.Monad.liftM"
,
"Control.Monad.liftM2"
,
"Control.Monad.liftM5"
]
"print $ List.intercal*"
`
completionHas
`
[
"List.intercalate"
]
"print $ Data.Maybe.cat*"
`
completionHas
`
[]
"print $ Maybe.catM*"
`
completionHas
`
[
"Maybe.catMaybes"
]
it
"properly completes imports"
$
do
"import Data.*"
`
completionHas
`
[
"Data.Maybe"
,
"Data.List"
]
"import Data.M*"
`
completionHas
`
[
"Data.Maybe"
]
"import Prel*"
`
completionHas
`
[
"Prelude"
]
testCommandCompletion
::
Spec
testCommandCompletion
=
describe
"Completes commands"
$
do
it
"properly completes haskell file paths on :load directive"
$
do
let
loading
xs
=
":load "
++
T
.
unpack
(
toTextIgnore
xs
)
paths
=
map
(
T
.
unpack
.
toTextIgnore
)
testInDirectory
start
comps
=
loading
start
`
shouldHaveCompletionsInDirectory
`
paths
comps
testInDirectory
(
"dir"
</>
"file*"
)
[
"dir"
</>
"file2.hs"
,
"dir"
</>
"file2.lhs"
]
testInDirectory
(
""
</>
"file1*"
)
[
""
</>
"file1.hs"
,
""
</>
"file1.lhs"
]
testInDirectory
(
""
</>
"file1*"
)
[
""
</>
"file1.hs"
,
""
</>
"file1.lhs"
]
testInDirectory
(
""
</>
"./*"
)
[
"./"
</>
"dir/"
,
"./"
</>
"file1.hs"
,
"./"
</>
"file1.lhs"
]
testInDirectory
(
""
</>
"./*"
)
[
"./"
</>
"dir/"
,
"./"
</>
"file1.hs"
,
"./"
</>
"file1.lhs"
]
it
"provides path completions on empty shell cmds "
$
":! cd *"
`
shouldHaveCompletionsInDirectory
`
map
(
T
.
unpack
.
toTextIgnore
)
[
""
</>
"dir/"
,
""
</>
"file1.hs"
,
""
</>
"file1.lhs"
]
let
withHsHome
action
=
withHsDirectory
$
\
dirPath
->
do
home
<-
shelly
$
Shelly
.
get_env_text
"HOME"
setHomeEvent
dirPath
result
<-
action
setHomeEvent
$
Shelly
.
fromText
home
return
result
setHomeEvent
path
=
liftIO
$
setEnv
"HOME"
(
T
.
unpack
$
toTextIgnore
path
)
it
"correctly interprets ~ as the environment HOME variable"
$
do
let
shouldHaveCompletions
::
String
->
[
String
]
->
IO
()
shouldHaveCompletions
string
expected
=
do
(
matched
,
completions
)
<-
withHsHome
$
completionEvent
string
let
existsInCompletion
=
(`
elem
`
completions
)
unmatched
=
filter
(
not
.
existsInCompletion
)
expected
expected
`
shouldBeAmong
`
completions
":! cd ~/*"
`
shouldHaveCompletions
`
[
"~/dir/"
]
":! ~/*"
`
shouldHaveCompletions
`
[
"~/dir/"
]
":load ~/*"
`
shouldHaveCompletions
`
[
"~/dir/"
]
":l ~/*"
`
shouldHaveCompletions
`
[
"~/dir/"
]
let
shouldHaveMatchingText
::
String
->
String
->
IO
()
shouldHaveMatchingText
string
expected
=
do
matchText
<-
withHsHome
$
fst
<$>
uncurry
complete
(
readCompletePrompt
string
)
matchText
`
shouldBe
`
expected
setHomeEvent
path
=
liftIO
$
setEnv
"HOME"
(
T
.
unpack
$
toTextIgnore
path
)
it
"generates the correct matchingText on `:! cd ~/*` "
$
":! cd ~/*"
`
shouldHaveMatchingText
`
(
"~/"
::
String
)
it
"generates the correct matchingText on `:load ~/*` "
$
":load ~/*"
`
shouldHaveMatchingText
`
(
"~/"
::
String
)
it
"generates the correct matchingText on `:l ~/*` "
$
":l ~/*"
`
shouldHaveMatchingText
`
(
"~/"
::
String
)
inDirectory
::
[
Shelly
.
FilePath
]
-- ^ directories relative to temporary directory
->
[
Shelly
.
FilePath
]
-- ^ files relative to temporary directory
->
(
Shelly
.
FilePath
->
Interpreter
a
)
->
IO
a
-- | Run an Interpreter action, but first make a temporary directory
-- with some files and folder and cd to it.
inDirectory
dirs
files
action
=
shelly
$
withTmpDir
$
\
dirPath
->
do
cd
dirPath
mapM_
mkdir_p
dirs
mapM_
touchfile
files
liftIO
$
ghc
$
wrap
(
T
.
unpack
$
toTextIgnore
dirPath
)
(
action
dirPath
)
where
cdEvent
path
=
liftIO
$
setCurrentDirectory
path
wrap
::
String
->
Interpreter
a
->
Interpreter
a
wrap
path
action
=
do
initCompleter
pwd
<-
IHaskell
.
Eval
.
Evaluate
.
liftIO
getCurrentDirectory
cdEvent
path
-- change to the temporary directory
out
<-
action
-- run action
cdEvent
pwd
-- change back to the original directory
return
out
withHsDirectory
::
(
Shelly
.
FilePath
->
Interpreter
a
)
->
IO
a
withHsDirectory
=
inDirectory
[
p
""
</>
p
"dir"
,
p
"dir"
</>
p
"dir1"
]
[
p
""
</>
p
"file1.hs"
,
p
"dir"
</>
p
"file2.hs"
,
p
""
</>
p
"file1.lhs"
,
p
"dir"
</>
p
"file2.lhs"
]
where
p
=
id
src/tests/IHaskell/Test/Eval.hs
0 → 100644
View file @
db351598
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE CPP #-}
module
IHaskell.Test.Eval
(
testEval
)
where
import
Prelude
import
Data.List
(
stripPrefix
)
import
Control.Monad
(
when
,
forM_
)
import
Data.IORef
(
newIORef
,
modifyIORef
,
readIORef
)
import
System.Directory
(
getTemporaryDirectory
,
setCurrentDirectory
)
import
Data.String.Here
(
hereLit
)
import
qualified
GHC.Paths
import
Test.Hspec
import
IHaskell.Test.Util
(
strip
)
import
IHaskell.Eval.Evaluate
(
interpret
,
evaluate
)
import
IHaskell.Types
(
EvaluationResult
(
..
),
defaultKernelState
,
KernelState
(
..
),
LintStatus
(
..
),
Display
(
..
),
extractPlain
)
eval
::
String
->
IO
([
Display
],
String
)
eval
string
=
do
outputAccum
<-
newIORef
[]
pagerAccum
<-
newIORef
[]
let
publish
evalResult
=
case
evalResult
of
IntermediateResult
{}
->
return
()
FinalResult
outs
page
[]
->
do
modifyIORef
outputAccum
(
outs
:
)
modifyIORef
pagerAccum
(
page
:
)
noWidgetHandling
s
_
=
return
s
getTemporaryDirectory
>>=
setCurrentDirectory
let
state
=
defaultKernelState
{
getLintStatus
=
LintOff
}
interpret
GHC
.
Paths
.
libdir
False
$
const
$
IHaskell
.
Eval
.
Evaluate
.
evaluate
state
string
publish
noWidgetHandling
out
<-
readIORef
outputAccum
pagerOut
<-
readIORef
pagerAccum
return
(
reverse
out
,
unlines
.
map
extractPlain
.
reverse
$
pagerOut
)
becomes
::
String
->
[
String
]
->
IO
()
becomes
string
expected
=
evaluationComparing
comparison
string
where
comparison
::
([
Display
],
String
)
->
IO
()
comparison
(
results
,
pageOut
)
=
do
when
(
length
results
/=
length
expected
)
$
expectationFailure
$
"Expected result to have "
++
show
(
length
expected
)
++
" results. Got "
++
show
results
forM_
(
zip
results
expected
)
$
\
(
ManyDisplay
[
Display
result
],
expected
)
->
case
extractPlain
result
of
""
->
expectationFailure
$
"No plain-text output in "
++
show
result
++
"
\n
Expected: "
++
expected
str
->
str
`
shouldBe
`
expected
evaluationComparing
::
(([
Display
],
String
)
->
IO
b
)
->
String
->
IO
b
evaluationComparing
comparison
string
=
do
let
indent
(
' '
:
x
)
=
1
+
indent
x
indent
_
=
0
empty
=
null
.
strip
stringLines
=
filter
(
not
.
empty
)
$
lines
string
minIndent
=
minimum
(
map
indent
stringLines
)
newString
=
unlines
$
map
(
drop
minIndent
)
stringLines
eval
newString
>>=
comparison
pages
::
String
->
[
String
]
->
IO
()
pages
string
expected
=
evaluationComparing
comparison
string
where
comparison
(
results
,
pageOut
)
=
strip
(
stripHtml
pageOut
)
`
shouldBe
`
strip
(
unlines
expected
)
-- A very, very hacky method for removing HTML
stripHtml
str
=
go
str
where
go
(
'<'
:
str
)
=
case
stripPrefix
"script"
str
of
Nothing
->
go'
str
Just
str
->
dropScriptTag
str
go
(
x
:
xs
)
=
x
:
go
xs
go
[]
=
[]
go'
(
'>'
:
str
)
=
go
str
go'
(
x
:
xs
)
=
go'
xs
go'
[]
=
error
$
"Unending bracket html tag in string "
++
str
dropScriptTag
str
=
case
stripPrefix
"</script>"
str
of
Just
str
->
go
str
Nothing
->
dropScriptTag
$
tail
str
testEval
::
Spec
testEval
=
describe
"Code Evaluation"
$
do
it
"evaluates expressions"
$
do
"3"
`
becomes
`
[
"3"
]
"3+5"
`
becomes
`
[
"8"
]
"print 3"
`
becomes
`
[
"3"
]
[
hereLit
|
let x = 11
z = 10 in
x+z
|]
`
becomes
`
[
"21"
]
it
"evaluates flags"
$
do
":set -package hello"
`
becomes
`
[
"Warning: -package not supported yet"
]
":set -XNoImplicitPrelude"
`
becomes
`
[]
it
"evaluates multiline expressions"
$
do
[
hereLit
|
import Control.Monad
forM_ [1, 2, 3] $ \x ->
print x
|]
`
becomes
`
[
"1
\n
2
\n
3"
]
it
"evaluates function declarations silently"
$
do
[
hereLit
|
fun :: [Int] -> Int
fun [] = 3
fun (x:xs) = 10
fun [1, 2]
|]
`
becomes
`
[
"10"
]
it
"evaluates data declarations"
$
do
[
hereLit
|
data X = Y Int
| Z String
deriving (Show, Eq)
print [Y 3, Z "No"]
print (Y 3 == Z "No")
|]
`
becomes
`
[
"[Y 3,Z
\"
No
\"
]"
,
"False"
]
it
"evaluates do blocks in expressions"
$
do
[
hereLit
|
show (show (do
Just 10
Nothing
Just 100))
|]
`
becomes
`
[
"
\"\\\"
Nothing
\\\"\"
"
]
it
"is silent for imports"
$
do
"import Control.Monad"
`
becomes
`
[]
"import qualified Control.Monad"
`
becomes
`
[]
"import qualified Control.Monad as CM"
`
becomes
`
[]
"import Control.Monad (when)"
`
becomes
`
[]
it
"evaluates directives"
$
do
":typ 3"
`
becomes
`
[
"3 :: forall a. Num a => a"
]
":k Maybe"
`
becomes
`
[
"Maybe :: * -> *"
]
#
if
MIN_VERSION_ghc
(
7
,
8
,
0
)
":in String"
`
pages
`
[
"type String = [Char]
\t
-- Defined in
\8216
GHC.Base
\8217
"
]
#
else
":in String"
`
pages
`
[
"type String = [Char]
\t
-- Defined in `GHC.Base'"
]
#
endif
src/tests/IHaskell/Test/Parser.hs
0 → 100644
View file @
db351598
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE CPP #-}
module
IHaskell.Test.Parser
(
testParser
)
where
import
Prelude
import
Data.String.Here
(
hereLit
)
import
Test.Hspec
import
Test.Hspec.HUnit
import
Test.HUnit
(
assertBool
,
assertFailure
)
import
IHaskell.Test.Util
(
ghc
,
strip
)
import
IHaskell.Eval.Parser
(
parseString
,
getModuleName
,
unloc
,
layoutChunks
,
Located
(
..
),
CodeBlock
(
..
),
DirectiveType
(
..
),
StringLoc
(
..
))
import
IHaskell.Eval.ParseShell
(
parseShell
)
parses
::
String
->
IO
[
CodeBlock
]
parses
str
=
map
unloc
<$>
ghc
(
parseString
str
)
like
::
(
Show
a
,
Eq
a
)
=>
IO
a
->
a
->
IO
()
like
parser
desired
=
parser
>>=
(`
shouldBe
`
desired
)
is
::
String
->
(
String
->
CodeBlock
)
->
IO
()
is
string
blockType
=
do
result
<-
ghc
$
parseString
string
map
unloc
result
`
shouldBe
`
[
blockType
$
strip
string
]
testParser
::
Spec
testParser
=
do
testLayoutChunks
testModuleNames
testParseString
testParseShell
testLayoutChunks
::
Spec
testLayoutChunks
=
describe
"Layout Chunk"
$
do
it
"chunks 'a string'"
$
map
unloc
(
layoutChunks
"a string"
)
`
shouldBe
`
[
"a string"
]
it
"chunks 'a
\\
n string'"
$
map
unloc
(
layoutChunks
"a
\n
string"
)
`
shouldBe
`
[
"a
\n
string"
]
it
"chunks 'a
\\
n string
\\
nextra'"
$
map
unloc
(
layoutChunks
"a
\n
string
\n
extra"
)
`
shouldBe
`
[
"a
\n
string"
,
"extra"
]
it
"chunks strings with too many lines"
$
map
unloc
(
layoutChunks
"a
\n\n
string"
)
`
shouldBe
`
[
"a"
,
"string"
]
it
"parses multiple exprs"
$
do
let
text
=
[
hereLit
|
first
second
third
fourth
|]
layoutChunks
text
`
shouldBe
`
[
Located
2
"first"
,
Located
4
"second"
,
Located
5
"third"
,
Located
7
"fourth"
]
testModuleNames
::
Spec
testModuleNames
=
describe
"Get Module Name"
$
do
it
"parses simple module names"
$
"module A where
\n
x = 3"
`
named
`
[
"A"
]
it
"parses module names with dots"
$
"module A.B where
\n
x = 3"
`
named
`
[
"A"
,
"B"
]
it
"parses module names with exports"
$
"module A.B.C ( x ) where x = 3"
`
named
`
[
"A"
,
"B"
,
"C"
]
it
"errors when given unnamed modules"
$
do
ghc
(
getModuleName
"x = 3"
)
`
shouldThrow
`
anyException
where
named
str
result
=
do
res
<-
ghc
$
getModuleName
str
res
`
shouldBe
`
result
testParseShell
::
Spec
testParseShell
=
describe
"Parsing Shell Commands"
$
do
test
"A"
[
"A"
]
test
":load A"
[
":load"
,
"A"
]
test
":!l ~/Downloads/MyFile
\\
Has
\\
Spaces.txt"
[
":!l"
,
"~/Downloads/MyFile
\\
Has
\\
Spaces.txt"
]
test
":!l
\"
~/Downloads/MyFile Has Spaces.txt
\"
/Another/File
\\
WithSpaces.doc"
[
":!l"
,
"~/Downloads/MyFile Has Spaces.txt"
,
"/Another/File
\\
WithSpaces.doc"
]
where
test
string
expected
=
it
(
"parses "
++
string
++
" correctly"
)
$
string
`
shouldParseTo
`
expected
shouldParseTo
xs
ys
=
case
parseShell
xs
of
Right
xs'
->
xs'
`
shouldBe
`
ys
Left
e
->
assertFailure
$
"parseShell returned error:
\n
"
++
show
e
testParseString
::
Spec
testParseString
=
describe
"Parser"
$
do
it
"parses empty strings"
$
parses
""
`
like
`
[]
it
"parses simple imports"
$
"import Data.Monoid"
`
is
`
Import
it
"parses simple arithmetic"
$
"3 + 5"
`
is
`
Expression
it
"parses :type"
$
parses
":type x
\n
:ty x"
`
like
`
[
Directive
GetType
"x"
,
Directive
GetType
"x"
]
it
"parses :info"
$
parses
":info x
\n
:in x"
`
like
`
[
Directive
GetInfo
"x"
,
Directive
GetInfo
"x"
]
it
"parses :help and :?"
$
parses
":? x
\n
:help x"
`
like
`
[
Directive
GetHelp
"x"
,
Directive
GetHelp
"x"
]
it
"parses :set x"
$
parses
":set x"
`
like
`
[
Directive
SetDynFlag
"x"
]
it
"parses :extension x"
$
parses
":ex x
\n
:extension x"
`
like
`
[
Directive
SetExtension
"x"
,
Directive
SetExtension
"x"
]
it
"fails to parse :nope"
$
parses
":nope goodbye"
`
like
`
[
ParseError
(
Loc
1
1
)
"Unknown directive: 'nope'."
]
it
"parses number followed by let stmt"
$
parses
"3
\n
let x = expr"
`
like
`
[
Expression
"3"
,
Statement
"let x = expr"
]
it
"parses let x in y"
$
"let x = 3 in x + 3"
`
is
`
Expression
it
"parses a data declaration"
$
"data X = Y Int"
`
is
`
Declaration
it
"parses number followed by type directive"
$
parses
"3
\n
:t expr"
`
like
`
[
Expression
"3"
,
Directive
GetType
"expr"
]
it
"parses a <- statement"
$
"y <- print 'no'"
`
is
`
Statement
it
"parses a <- stmt followed by let stmt"
$
parses
"y <- do print 'no'
\n
let x = expr"
`
like
`
[
Statement
"y <- do print 'no'"
,
Statement
"let x = expr"
]
it
"parses <- followed by let followed by expr"
$
parses
"y <- do print 'no'
\n
let x = expr
\n
expression"
`
like
`
[
Statement
"y <- do print 'no'"
,
Statement
"let x = expr"
,
Expression
"expression"
]
it
"parses two print statements"
$
parses
"print yes
\n
print no"
`
like
`
[
Expression
"print yes"
,
Expression
"print no"
]
it
"parses a pattern-maching function declaration"
$
"fun [] = 10"
`
is
`
Declaration
it
"parses a function decl followed by an expression"
$
parses
"fun [] = 10
\n
print 'h'"
`
like
`
[
Declaration
"fun [] = 10"
,
Expression
"print 'h'"
]
it
"parses list pattern matching fun decl"
$
"fun (x : xs) = 100"
`
is
`
Declaration
it
"parses two pattern matches as the same declaration"
$
"fun [] = 10
\n
fun (x : xs) = 100"
`
is
`
Declaration
it
"parses a type signature followed by a declaration"
$
"fun :: [a] -> Int
\n
fun [] = 10
\n
fun (x : xs) = 100"
`
is
`
Declaration
it
"parases a simple module"
$
"module A where x = 3"
`
is
`
Module
it
"parses a module with an export"
$
"module B (x) where x = 3"
`
is
`
Module
it
"breaks when a let is incomplete"
$
parses
"let x = 3 in"
`
like
`
[
ParseError
(
Loc
1
13
)
"parse error (possibly incorrect indentation or mismatched brackets)"
]
it
"breaks without data kinds"
$
parses
"data X = 3"
`
like
`
[
dataKindsError
]
it
"parses statements after imports"
$
do
parses
"import X
\n
print 3"
`
like
`
[
Import
"import X"
,
Expression
"print 3"
]
parses
"import X
\n\n
print 3"
`
like
`
[
Import
"import X"
,
Expression
"print 3"
]
it
"ignores blank lines properly"
$
[
hereLit
|
test arg = hello
where
x = y
z = w
|]
`
is
`
Declaration
it
"doesn't break on long strings"
$
do
let
longString
=
concat
$
replicate
20
"hello "
(
"img ! src
\"
"
++
longString
++
"
\"
! width
\"
500
\"
"
)
`
is
`
Expression
it
"parses do blocks in expression"
$
do
[
hereLit
|
show (show (do
Just 10
Nothing
Just 100))
|]
`
is
`
Expression
it
"correctly locates parsed items"
$
do
ghc
(
parseString
[
hereLit
|
first
second
|]
)
>>=
(`
shouldBe
`
[
Located
2
(
Expression
"first"
),
Located
4
(
Expression
"second"
)])
where
dataKindsError
=
ParseError
(
Loc
1
10
)
msg
#
if
MIN_VERSION_ghc
(
7
,
10
,
0
)
msg
=
"Cannot parse data constructor in a data/newtype declaration: 3"
#
elif
MIN_VERSION_ghc
(
7
,
8
,
0
)
msg
=
"Illegal literal in type (use DataKinds to enable): 3"
#
else
msg
=
"Illegal literal in type (use -XDataKinds to enable): 3"
#
endif
src/tests/IHaskell/Test/Util.hs
0 → 100644
View file @
db351598
module
IHaskell.Test.Util
(
lstrip
,
rstrip
,
strip
,
replace
,
ghc
,
shouldBeAmong
)
where
import
Prelude
import
qualified
Data.Text
as
T
import
Test.HUnit
(
assertBool
)
import
GHC
import
qualified
GHC.Paths
-- | Drop whitespace from the left of a string.
lstrip
::
String
->
String
lstrip
=
dropWhile
(`
elem
`
(
"
\t\r\n
"
::
String
))
-- | Drop whitespace from the right of a string.
rstrip
::
String
->
String
rstrip
=
reverse
.
lstrip
.
reverse
-- | Drop whitespace from both sides of a string.
strip
::
String
->
String
strip
=
rstrip
.
lstrip
-- | Replace all occurrences of a string with another string.
replace
::
String
->
String
->
String
->
String
replace
needle
replacement
haystack
=
T
.
unpack
$
T
.
replace
(
T
.
pack
needle
)
(
T
.
pack
replacement
)
(
T
.
pack
haystack
)
ghc
::
Ghc
a
->
IO
a
ghc
=
runGhc
(
Just
GHC
.
Paths
.
libdir
)
--
-- | @sublist \`shouldbeAmong\` list@ sets the expectation that @sublist@ elements are
-- among those in @list@.
shouldBeAmong
::
(
Show
a
,
Eq
a
)
=>
[
a
]
->
[
a
]
->
IO
()
sublist
`
shouldBeAmong
`
list
=
assertBool
errorMsg
$
and
[
x
`
elem
`
list
|
x
<-
sublist
]
where
errorMsg
=
show
list
++
" doesn't contain "
++
show
sublist
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment