forked from facebookincubator/hsthrift
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathServiceTest.hs
125 lines (105 loc) · 3.27 KB
/
ServiceTest.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
-- Copyright (c) Facebook, Inc. and its affiliates.
{-# OPTIONS_GHC -fno-warn-unused-imports #-}
module ServiceTest where
import Data.Either.Combinators
import Test.HUnit
import TestRunner
import qualified Data.Map.Strict as Map
import Thrift.Compiler.Options
import Thrift.Compiler.Parser
import Thrift.Compiler.Plugins.Linter
import Thrift.Compiler.Typechecker
import Thrift.Compiler.Typechecker.Monad
import Thrift.Compiler.Types
-- This import just makes sure the file compiles
import Service.Types
-- Invalid Inputs --------------------------------------------------------------
superCycle :: Test
superCycle = expectTypeError "super service cycle" $ unlines
[ "service X extends Y {}"
, "service Y extends X {}"
]
unknownService :: Test
unknownService = expectTypeError "reference service that doesn't exist"
"service X extends Y {}"
unknownType :: Test
unknownType = expectTypeError "unknown type" $ unlines
[ "service X {"
, " void myFunction(1: Y notARealType)"
, "}"
]
duplicateFunction :: Test
duplicateFunction = expectTypeError "duplicate function" $ unlines
[ "service X {"
, " void myFunction();"
, " i64 myFunction();"
, "}"
]
duplicateFunctionSuper :: Test
duplicateFunctionSuper = expectTypeError "duplicate function super" $ unlines
[ "service X {"
, " void myFunction()"
, "}"
, "service Y extends X {"
, " i64 myFunction()"
, "}"
]
optionalArgument :: Test
optionalArgument = expectParseError "optional argument" $ unlines
[ "service X {"
, " void myFunction(1: optional i64 x)"
, "}"
]
duplicateArgIds :: Test
duplicateArgIds = expectTypeError "duplicate argument ids" $ unlines
[ "service X {"
, " void myFunction(1: i32 x, 1: i64 y)"
, "}"
]
duplicateExcIds :: Test
duplicateExcIds = expectTypeError "duplicate exception ids" $ unlines
[ "exception A {}"
, "exception B {}"
, "service X {"
, " void myFunction() throws(1: A a, 1: B b)"
, "}"
]
--------------------------------------------------------------------------------
data Error = ParseError String | TypeErrors [TypeError Linter]
parseAndTypecheck
:: String -> Either Error (Program Linter Loc, [Program Linter Loc])
parseAndTypecheck input =
case runParser parseThrift "<untitled>" input of
Left err -> Left $ ParseError err
Right tFile ->
mapLeft TypeErrors $ typecheck (defaultOptions NoOpts) (mkModuleMap tFile)
mkModuleMap :: ([Parsed Header], [Parsed Decl]) -> ModuleMap
mkModuleMap (headers, decls) =
Map.singleton "" ThriftFile
{ thriftName = ""
, thriftPath = ""
, thriftHeaders = headers
, thriftDecls = decls
, thriftSplice = Nothing
, thriftComments = []
}
expectTypeError :: String -> String -> Test
expectTypeError label input = TestLabel label $ TestCase $
case parseAndTypecheck input of
Left TypeErrors{} -> return ()
_ -> assertFailure "should be a type error"
expectParseError :: String -> String -> Test
expectParseError label input = TestLabel label $ TestCase $
case parseAndTypecheck input of
Left ParseError{} -> return ()
_ -> assertFailure "should be a parse error"
main :: IO ()
main = testRunner $ TestList
[ superCycle
, unknownService
, unknownType
, duplicateFunction
, duplicateFunctionSuper
, optionalArgument
, duplicateArgIds, duplicateExcIds
]