blob: 340b58b68cc9184313ccedc34eb975e4106f8fb2 [file] [log] [blame]
Noam Zilbersteinaf5d64a2014-07-31 15:44:13 -07001--
2-- Licensed to the Apache Software Foundation (ASF) under one
3-- or more contributor license agreements. See the NOTICE file
4-- distributed with this work for additional information
5-- regarding copyright ownership. The ASF licenses this file
6-- to you under the Apache License, Version 2.0 (the
7-- "License"); you may not use this file except in compliance
8-- with the License. You may obtain a copy of the License at
9--
10-- http://www.apache.org/licenses/LICENSE-2.0
11--
12-- Unless required by applicable law or agreed to in writing,
13-- software distributed under the License is distributed on an
14-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15-- KIND, either express or implied. See the License for the
16-- specific language governing permissions and limitations
17-- under the License.
18--
19
20{-# LANGUAGE OverloadedStrings,RecordWildCards #-}
21module Main where
22
23import Control.Exception
24import Control.Monad
25import Data.Functor
26import Data.HashMap.Strict (HashMap)
27import Data.List
28import Data.String
29import Network
30import System.Environment
31import System.Exit
32import System.IO
33import System.Posix.Unistd
34import qualified Data.HashMap.Strict as Map
35import qualified Data.HashSet as Set
36import qualified Data.Text.Lazy as Text
37import qualified Data.Vector as Vector
38
39import ThriftTest
40import ThriftTest_Iface
41import ThriftTest_Types
42
43import Thrift
44import Thrift.Server
45import Thrift.Transport.Framed
46import Thrift.Transport.Handle
47import Thrift.Protocol.Binary
48import Thrift.Protocol.Compact
49import Thrift.Protocol.JSON
50
51data Options = Options
52 { port :: Int
53 , domainSocket :: String
54 , serverType :: ServerType
55 , transport :: String
56 , protocol :: ProtocolType
57 , ssl :: Bool
58 , workers :: Int
59 }
60
61data ServerType = Simple
62 | ThreadPool
63 | Threaded
64 | NonBlocking
65 deriving (Show, Eq)
66
67instance IsString ServerType where
68 fromString "simple" = Simple
69 fromString "thread-pool" = ThreadPool
70 fromString "threaded" = Threaded
71 fromString "nonblocking" = NonBlocking
72 fromString _ = error "not a valid server type"
73
74data ProtocolType = Binary
75 | Compact
76 | JSON
77
78getProtocol :: String -> ProtocolType
79getProtocol "binary" = Binary
80getProtocol "compact" = Compact
81getProtocol "json" = JSON
82getProtocol p = error $"Unsupported Protocol: " ++ p
83
84defaultOptions :: Options
85defaultOptions = Options
86 { port = 9090
87 , domainSocket = ""
88 , serverType = Threaded
89 , transport = "framed"
90 , protocol = Binary
91 , ssl = False
92 , workers = 4
93 }
94
95stringifyMap :: (Show a, Show b) => Map.HashMap a b -> String
96stringifyMap = intercalate ", " . map joinKV . Map.toList
97 where joinKV (k, v) = show k ++ " => " ++ show v
98
99stringifySet :: Show a => Set.HashSet a -> String
100stringifySet = intercalate ", " . map show . Set.toList
101
102stringifyList :: Show a => Vector.Vector a -> String
103stringifyList = intercalate ", " . map show . Vector.toList
104
105data TestHandler = TestHandler
106instance ThriftTest_Iface TestHandler where
107 testVoid _ = putStrLn "testVoid()"
108
109 testString _ s = do
110 putStrLn $ "testString(" ++ show s ++ ")"
111 return s
112
113 testByte _ x = do
114 putStrLn $ "testByte(" ++ show x ++ ")"
115 return x
116
117 testI32 _ x = do
118 putStrLn $ "testI32(" ++ show x ++ ")"
119 return x
120
121 testI64 _ x = do
122 putStrLn $ "testI64(" ++ show x ++ ")"
123 return x
124
125 testDouble _ x = do
126 putStrLn $ "testDouble(" ++ show x ++ ")"
127 return x
128
129 testStruct _ struct@Xtruct{..} = do
130 putStrLn $ "testStruct({" ++ show xtruct_string_thing
131 ++ ", " ++ show xtruct_byte_thing
132 ++ ", " ++ show xtruct_i32_thing
133 ++ ", " ++ show xtruct_i64_thing
134 ++ "})"
135 return struct
136
137 testNest _ nest@Xtruct2{..} = do
138 let Xtruct{..} = xtruct2_struct_thing
139 putStrLn $ "testNest({" ++ show xtruct2_byte_thing
140 ++ "{, " ++ show xtruct_string_thing
141 ++ ", " ++ show xtruct_byte_thing
142 ++ ", " ++ show xtruct_i32_thing
143 ++ ", " ++ show xtruct_i64_thing
144 ++ "}, " ++ show xtruct2_i32_thing
145 return nest
146
147 testMap _ m = do
148 putStrLn $ "testMap({" ++ stringifyMap m ++ "})"
149 return m
150
151 testStringMap _ m = do
152 putStrLn $ "testStringMap(" ++ stringifyMap m ++ "})"
153 return m
154
155 testSet _ x = do
156 putStrLn $ "testSet({" ++ stringifySet x ++ "})"
157 return x
158
159 testList _ x = do
160 putStrLn $ "testList(" ++ stringifyList x ++ "})"
161 return x
162
163 testEnum _ x = do
164 putStrLn $ "testEnum(" ++ show x ++ ")"
165 return x
166
167 testTypedef _ x = do
168 putStrLn $ "testTypedef(" ++ show x ++ ")"
169 return x
170
171 testMapMap _ x = do
172 putStrLn $ "testMapMap(" ++ show x ++ ")"
173 return $ Map.fromList [ (-4, Map.fromList [ (-4, -4)
174 , (-3, -3)
175 , (-2, -2)
176 , (-1, -1)
177 ])
178 , (4, Map.fromList [ (1, 1)
179 , (2, 2)
180 , (3, 3)
181 , (4, 4)
182 ])
183 ]
184
185 testInsanity _ x = do
186 putStrLn "testInsanity()"
187 return $ Map.fromList [ (1, Map.fromList [ (TWO , x)
188 , (THREE, x)
189 ])
190 , (2, Map.fromList [ (SIX, default_Insanity)
191 ])
192 ]
193
194 testMulti _ byte i32 i64 _ _ _ = do
195 putStrLn "testMulti()"
196 return Xtruct{ xtruct_string_thing = Text.pack "Hello2"
197 , xtruct_byte_thing = byte
198 , xtruct_i32_thing = i32
199 , xtruct_i64_thing = i64
200 }
201
202 testException _ s = do
203 putStrLn $ "testException(" ++ show s ++ ")"
204 case s of
205 "Xception" -> throw $ Xception 1001 s
206 "TException" -> throw ThriftException
207 _ -> return ()
208
209 testMultiException _ s1 s2 = do
210 putStrLn $ "testMultiException(" ++ show s1 ++ ", " ++ show s2 ++ ")"
211 case s1 of
212 "Xception" -> throw $ Xception 1001 "This is an Xception"
213 "Xception2" -> throw $ Xception2 2002 default_Xtruct
214 "TException" -> throw ThriftException
215 _ -> return default_Xtruct{ xtruct_string_thing = s2 }
216
217 testOneway _ i = do
218 putStrLn $ "testOneway(" ++ show i ++ "): Sleeping..."
219 sleep (fromIntegral i)
220 putStrLn $ "testOneway(" ++ show i ++ "): done sleeping!"
221
222main :: IO ()
223main = do
224 options <- flip parseFlags defaultOptions <$> getArgs
225 case options of
226 Nothing -> showHelp
227 Just Options{..} -> do
228 putStrLn $ "Starting \"" ++ show serverType ++ "\" server (" ++
229 show transport ++ ") listen on: " ++ domainSocket ++ show port
230 case protocol of
231 Binary -> runServer BinaryProtocol port
232 Compact -> runServer CompactProtocol port
233 JSON -> runServer JSONProtocol port
234 where
235 runServer p = runThreadedServer (accepter p) TestHandler ThriftTest.process . PortNumber . fromIntegral
236 accepter p s = do
237 (h, _, _) <- accept s
238 return (p h, p h)
239
240parseFlags :: [String] -> Options -> Maybe Options
241parseFlags (flag : arg : flags) opts
242 | flag == "--port" = parseFlags flags opts{ port = read arg }
243 | flag == "--domain-socket" = parseFlags flags opts{ domainSocket = arg }
244 | flag == "--server-type" = parseFlags flags opts{ serverType = fromString arg }
245 | flag == "--transport" = parseFlags flags opts{ transport = arg }
246 | flag == "--protocol" = parseFlags flags opts{ protocol = getProtocol arg }
247 | flag == "-n" ||
248 flag == "--workers" = parseFlags flags opts{ workers = read arg }
249parseFlags (flag : flags) opts
250 | flag == "-h" = Nothing
251 | flag == "--help" = Nothing
252 | flag == "--ssl" = parseFlags flags opts{ ssl = True }
253 | flag == "--processor-events" = parseFlags flags opts
254parseFlags [] opts = Just opts
255
256showHelp :: IO ()
257showHelp = putStrLn
258 "Allowed options:\n\
259 \ -h [ --help ] produce help message\n\
260 \ --port arg (=9090) Port number to listen\n\
261 \ --domain-socket arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift)\n\
262 \ --server-type arg (=simple) type of server, \"simple\", \"thread-pool\",\n\
263 \ \"threaded\", or \"nonblocking\"\n\
264 \ --transport arg (=buffered) transport: buffered, framed, http\n\
265 \ --protocol arg (=binary) protocol: binary, compact, json\n\
266 \ --ssl Encrypted Transport using SSL\n\
267 \ --processor-events processor-events\n\
268 \ -n [ --workers ] arg (=4) Number of thread pools workers. Only valid for\n\
269 \ thread-pool server type"