blob: 6817981266c67b81bf1a4e91dceef6b2c969024a [file] [log] [blame]
Kino Roya9da9eb2022-10-07 23:13:01 -07001// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18import Foundation
19import Thrift
20import Common
21import XCTest
22
23enum Error: Int32 {
24 case baseTypes = 1
25 case structs = 2
26 case containers = 4
27 case exceptions = 8
28 case unknown = 64
29 case timeout = 128
30}
31
32class TestClient {
33 var client: ThriftTestClient
34 var resultCode: Int32 = 0
35
36 public init(parameters: TestClientParameters) throws {
37 let transport = try TestClient.getTransport(parameters: parameters)
38 let proto = try TestClient.getProtocol(parameters: parameters, transport: transport)
39 client = ThriftTestClient(inoutProtocol: proto)
40 }
41
42 static func getTransport(parameters: TestClientParameters) throws -> TTransport {
43 let socketTransport = try TSocketTransport(hostname: parameters.host!, port: parameters.port!)
44 if parameters.transport == .framed {
45 return TFramedTransport(transport: socketTransport)
46 }
47
48 if parameters.transport == .buffered {
49 return socketTransport
50 }
51
52 throw ParserError.unsupportedOption
53 }
54
55 static func getProtocol(parameters: TestClientParameters, transport: TTransport) throws -> TProtocol {
56 if parameters.proto == .binary {
57 return TBinaryProtocol(on: transport)
58 }
59
60 if parameters.proto == .compact {
61 return TCompactProtocol(on: transport)
62 }
63
64 throw ParserError.unsupportedOption
65 }
66
67 func run() throws {
68 do {
69 try testVoid()
70 try testString()
71 try testBool()
72 try testByte()
73 try testI32()
74 try testI64()
75 try testDouble()
76 try testBinary()
77 try testStruct()
78 try testNest()
79 try testMap()
80 try testSet()
81 try testList()
82 try testEnum()
83 try testTypedef()
84 try testMapMap()
85 try testInsanity()
86 try testMulti()
87 try testException()
88 try testMultiException()
89 // Swift generator doesn't yet support one way functions (THRIFT-5468)
90 /*try testOneway()
91 try testOnewayThenNormal()*/
92 try testUuid()
93
94 } catch let error {
95 print("\(error)")
96 resultCode |= Error.unknown.rawValue
97 }
98 exit(resultCode)
99 }
100
101 func testVoid() throws {
102 print("testVoid")
103 try client.testVoid()
104 }
105
106
107 func testString1(_ s1: String) throws {
108 print("testString(\(s1))")
109 let r1 = try client.testString(thing: s1)
110 print(r1)
111 if s1 != r1 {
112 resultCode |= Error.baseTypes.rawValue
113 }
114 }
115
116 func testString() throws {
117 try testString1(String(repeating: "Python", count: 20))
118 try testString1("")
119 try testString1("\t\n/\\\\\r{}:パイソン")
120 try testString1("""
121Afrikaans, Alemannisch, Aragonés, العربية, مصرى,
122Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška,
123Беларуская, Беларуская (тарашкевіца), Български, Bamanankan,
124বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн,
125Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg,
126Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English,
127Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt,
128Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego,
129Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski,
130Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia,
131Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa,
132ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар,
133Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino,
134Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa
135Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, مازِرونی, Bahasa
136Melayu, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪
137Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad,
138Occitan, Иронау, Papiamentu, Deitsch, Polski, پنجابی, پښتو,
139Norfuk / Pitkern, Português, Runa Simi, Rumantsch, Romani, Română,
140Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple
141English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk,
142Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog,
143Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük,
144Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文,
145Bân-lâm-gú, 粵語
146""")
147 }
148
149 func testBool1(_ s1: Bool) throws {
150 print("testBool(\(s1))")
151 let r1 = try client.testBool(thing: s1)
152 print(r1)
153 if s1 != r1 {
154 resultCode |= Error.baseTypes.rawValue
155 }
156 }
157
158 func testBool() throws {
159 try testBool1(true)
160 try testBool1(false)
161 }
162
163 func testByte() throws {
164 print("testByte")
165 if try client.testByte(thing: 63) != 63 {
166 resultCode |= Error.baseTypes.rawValue
167 }
168 if try client.testByte(thing: -127) != -127 {
169 resultCode |= Error.baseTypes.rawValue
170 }
171 }
172
173 func testI32() throws {
174 print("testI32")
175 if try client.testI32(thing: -1) != -1 {
176 resultCode |= Error.baseTypes.rawValue
177 }
178 if try client.testI32(thing: 0) != 0 {
179 resultCode |= Error.baseTypes.rawValue
180 }
181 }
182
183 func testI64() throws {
184 print("testI64")
185 if try client.testI64(thing: 1) != 1 ||
186 client.testI64(thing: -34359738368) != -34359738368 {
187 resultCode |= Error.baseTypes.rawValue
188 }
189 }
190
191 func testDouble() throws {
192 print("testDouble")
193 for testValue in [-5.235098235, 0, -1, -0.000341012439638598279] {
194 if try client.testDouble(thing: testValue) != testValue {
195 resultCode |= Error.baseTypes.rawValue
196 }
197 }
198 }
199
200 func testBinary() throws {
201 print("testBinary")
202 let val = Data(Array(0...255))
203 if try client.testBinary(thing: val) != val {
204 resultCode |= Error.baseTypes.rawValue
205 }
206 }
207
208 func testStruct() throws {
209 print("testStruct")
210 let x = Xtruct(string_thing: "Zero", byte_thing: 1, i32_thing: -3, i64_thing: -5)
211 if try client.testStruct(thing: x) != x {
212 resultCode |= Error.structs.rawValue
213 }
214 }
215
216 func testNest() throws {
217 print("testNest")
218 let inner = Xtruct(string_thing: "Zero", byte_thing: 1, i32_thing: -3, i64_thing: -5)
219 let x = Xtruct2(byte_thing: 0, struct_thing: inner, i32_thing: 0)
220 if try client.testNest(thing: x) != x {
221 resultCode |= Error.structs.rawValue
222 }
223 }
224
225 func testMap() throws {
226 print("testMap")
227 let x = TMap<Int32, Int32>([0: 1, 1: 2, 2: 3, 3: 4, -1: -2])
228 if try client.testMap(thing: x) != x {
229 resultCode |= Error.containers.rawValue
230 }
231 }
232
233 func testSet() throws {
234 print("testSet")
235 let x = TSet<Int32>([8, 1, 42])
236 if try client.testSet(thing: x) != x {
237 resultCode |= Error.containers.rawValue
238 }
239 }
240
241 func testList() throws {
242 print("testList")
243 let x = TList<Int32>([1, 4, 9, -42])
244 if try client.testList(thing: x) != x {
245 resultCode |= Error.containers.rawValue
246 }
247 }
248
249 func testEnum() throws {
250 print("testEnum")
251 let x = Numberz.five
252 if try client.testEnum(thing: x) != x {
253 resultCode |= Error.containers.rawValue
254 }
255 }
256
257 func testTypedef() throws {
258 print("testTypedef")
259 let x = UserId(bitPattern: 0xffffffffffffff)
260 if try client.testTypedef(thing: x) != x {
261 resultCode |= Error.containers.rawValue
262 }
263 }
264
265 func testMapMap() throws {
266 print("testMapMap")
267 let x = TMap<Int32, TMap<Int32, Int32>>([
268 -4: [-4: -4, -3: -3, -2: -2, -1: -1],
269 4: [4: 4, 3: 3, 2: 2, 1: 1]
270 ])
271 if try client.testMapMap(hello: 42) != x {
272 resultCode |= Error.containers.rawValue
273 }
274 }
275
276 func testInsanity() throws {
277 print("testInsanity()")
278 let argument = Insanity(userMap: [.eight: 8], xtructs: [])
279 let expected = TMap<UserId, TMap<Numberz, Insanity>>([
280 1: [
281 .two: argument,
282 .three: argument
283 ],
284 2: [
285 .six: Insanity(userMap: [:], xtructs: [])
286 ]
287 ])
288 if try client.testInsanity(argument: argument) != expected {
289 resultCode |= Error.containers.rawValue
290 }
291 }
292
293 func testMulti() throws {
294 print("testMulti")
295 let x = Xtruct(string_thing: "Hello2", byte_thing: 74, i32_thing: 0xff00ff, i64_thing: 0xffffffffd0d0)
296 if try client.testMulti(arg0: x.byte_thing, arg1: x.i32_thing, arg2: x.i64_thing, arg3: .init([0: "abc"]), arg4: Numberz.five, arg5: 0xf0f0f0) != x {
297 resultCode |= Error.containers.rawValue
298 }
299 }
300
301 func testException() throws {
302 print("testException")
303 try client.testException(arg: "Safe")
304 do {
305 try client.testException(arg: "Xception")
306 resultCode |= Error.exceptions.rawValue
307 } catch let error as Xception {
308 guard error.errorCode == 1001, error.message == "Xception" else {
309 resultCode |= Error.exceptions.rawValue
310 return
311 }
312 } catch {
313 resultCode |= Error.exceptions.rawValue
314 }
315
316 do {
317 try client.testException(arg: "TException")
318 resultCode |= Error.exceptions.rawValue
319 } catch is TError {
320
321 } catch {
322 resultCode |= Error.exceptions.rawValue
323 }
324
325 try client.testException(arg: "success")
326 }
327
328 func testMultiException() throws {
329 print("testMultiException")
330 do {
331 _ = try client.testMultiException(arg0: "Xception", arg1: "ignore")
332 } catch let error as Xception {
333 guard error.errorCode == 1001, error.message == "This is an Xception" else {
334 resultCode |= Error.exceptions.rawValue
335 return
336 }
337 } catch {
338 resultCode |= Error.exceptions.rawValue
339 }
340
341 do {
342 _ = try client.testMultiException(arg0: "Xception2", arg1: "ignore")
343 } catch let error as Xception2 {
344 guard error.errorCode == 2002, error.struct_thing.string_thing == "This is an Xception2" else {
345 resultCode |= Error.exceptions.rawValue
346 return
347 }
348 }
349
350 let y = try client.testMultiException(arg0: "success", arg1: "foobar")
351 if y.string_thing != "foobar" {
352 resultCode |= Error.exceptions.rawValue
353 }
354 }
355
356 // Swift generator doesn't yet support one way functions (THRIFT-5468)
357 /*func testOneway() throws {
358 print("testOneway")
359 let start = CACurrentMediaTime()
360 try client.testOneway(secondsToSleep: 1)
361 let end = CACurrentMediaTime()
362 let duration = end - start
363 let delta = abs(1 - duration)
364 print("oneway sleep took \(end - start) sec")
365
366 guard delta < 0.5 else {
367 print("oneway sleep took \(end - start) sec")
368 resultCode |= Error.unknown.rawValue
369 return
370 }
371 }
372
373 func testOnewayThenNormal() throws {
374 print("testOnewayThenNormal")
375 try client.testOneway(secondsToSleep: 1)
376 if try client.testString(thing: "Swift") != "Swift" {
377 resultCode |= Error.baseTypes.rawValue
378 }
379 }*/
380
381 func testUuid() throws {
382 let uuid = UUID()
383 guard try client.testUuid(thing: uuid) == uuid else {
384 resultCode |= Error.baseTypes.rawValue
385 return
386 }
387 }
388}
389
390
391let parameters = try TestClientParameters(arguments: CommandLine.arguments)
392
393if parameters.showHelp {
394 parameters.printHelp()
395 exit(0)
396}
397
398Thread.sleep(forTimeInterval: 1)
399
400try TestClient(parameters: parameters).run()