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