]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | /// 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 | ||
18 | import 'dart:async'; | |
19 | import 'dart:convert'; | |
20 | import 'dart:io'; | |
21 | ||
22 | import 'package:args/args.dart'; | |
23 | import 'package:collection/collection.dart'; | |
24 | import 'package:http/http.dart' as http; | |
25 | import 'package:thrift/thrift.dart'; | |
26 | import 'package:thrift/thrift_console.dart'; | |
27 | import 'package:thrift_test/thrift_test.dart'; | |
28 | ||
29 | const TEST_BASETYPES = 1; // 0000 0001 | |
30 | const TEST_STRUCTS = 2; // 0000 0010 | |
31 | const TEST_CONTAINERS = 4; // 0000 0100 | |
32 | const TEST_EXCEPTIONS = 8; // 0000 1000 | |
33 | const TEST_UNKNOWN = 64; // 0100 0000 (Failed to prepare environemt etc.) | |
34 | const TEST_TIMEOUT = 128; // 1000 0000 | |
35 | const TEST_NOTUSED = 48; // 0011 0000 (reserved bits) | |
36 | ||
37 | typedef Future FutureFunction(); | |
38 | ||
39 | class TTest { | |
40 | final int errorCode; | |
41 | final String name; | |
42 | final FutureFunction func; | |
43 | ||
44 | TTest(this.errorCode, this.name, this.func); | |
45 | } | |
46 | ||
47 | class TTestError extends Error { | |
48 | final actual; | |
49 | final expected; | |
50 | ||
51 | TTestError(this.actual, this.expected); | |
52 | ||
53 | String toString() => '$actual != $expected'; | |
54 | } | |
55 | ||
56 | List<TTest> _tests; | |
57 | ThriftTestClient client; | |
58 | bool verbose; | |
59 | ||
60 | /// Adapted from TestClient.php | |
61 | main(List<String> args) async { | |
62 | ArgResults results = _parseArgs(args); | |
63 | ||
64 | if (results == null) { | |
65 | exit(TEST_UNKNOWN); | |
66 | } | |
67 | ||
68 | verbose = results['verbose'] == true; | |
69 | ||
70 | await _initTestClient( | |
71 | host: results['host'], | |
72 | port: int.parse(results['port']), | |
73 | transportType: results['transport'], | |
74 | protocolType: results['protocol']).catchError((e) { | |
75 | stdout.writeln('Error:'); | |
76 | stdout.writeln('$e'); | |
77 | if (e is Error) { | |
78 | stdout.writeln('${e.stackTrace}'); | |
79 | } | |
80 | exit(TEST_UNKNOWN); | |
81 | }); | |
82 | ||
83 | // run tests | |
84 | _tests = _createTests(); | |
85 | ||
86 | int result = 0; | |
87 | ||
88 | for (TTest test in _tests) { | |
89 | if (verbose) stdout.write('${test.name}... '); | |
90 | try { | |
91 | await test.func(); | |
92 | if (verbose) stdout.writeln('success!'); | |
93 | } catch (e) { | |
94 | if (verbose) stdout.writeln('$e'); | |
95 | result = result | test.errorCode; | |
96 | } | |
97 | } | |
98 | ||
99 | exit(result); | |
100 | } | |
101 | ||
102 | ArgResults _parseArgs(List<String> args) { | |
103 | var parser = new ArgParser(); | |
104 | parser.addOption('host', defaultsTo: 'localhost', help: 'The server host'); | |
105 | parser.addOption('port', defaultsTo: '9090', help: 'The port to connect to'); | |
106 | parser.addOption('transport', | |
107 | defaultsTo: 'buffered', | |
108 | allowed: ['buffered', 'framed', 'http'], | |
109 | help: 'The transport name', | |
110 | allowedHelp: { | |
111 | 'buffered': 'TBufferedTransport', | |
112 | 'framed': 'TFramedTransport' | |
113 | }); | |
114 | parser.addOption('protocol', | |
115 | defaultsTo: 'binary', | |
116 | allowed: ['binary', 'compact', 'json'], | |
117 | help: 'The protocol name', | |
118 | allowedHelp: { | |
119 | 'binary': 'TBinaryProtocol', | |
120 | 'compact': 'TCompactProtocol', | |
121 | 'json': 'TJsonProtocol' | |
122 | }); | |
123 | parser.addFlag('verbose', defaultsTo: true); | |
124 | ||
125 | ArgResults results; | |
126 | try { | |
127 | results = parser.parse(args); | |
128 | } catch (e) { | |
129 | stdout.writeln('$e\n'); | |
130 | } | |
131 | ||
132 | if (results == null) stdout.write(parser.usage); | |
133 | ||
134 | return results; | |
135 | } | |
136 | ||
137 | TProtocolFactory getProtocolFactory(String protocolType) { | |
138 | if (protocolType == 'binary') { | |
139 | return new TBinaryProtocolFactory(); | |
140 | } else if (protocolType == 'compact') { | |
141 | return new TCompactProtocolFactory(); | |
142 | } else if (protocolType == 'json') { | |
143 | return new TJsonProtocolFactory(); | |
144 | } | |
145 | ||
146 | throw new ArgumentError.value(protocolType); | |
147 | } | |
148 | ||
149 | Future _initTestClient( | |
150 | {String host, int port, String transportType, String protocolType}) async { | |
151 | TTransport transport; | |
152 | var protocolFactory = getProtocolFactory(protocolType); | |
153 | ||
154 | if (transportType == 'http') { | |
155 | var httpClient = new http.IOClient(); | |
156 | var uri = Uri.parse('http://$host:$port'); | |
157 | var config = new THttpConfig(uri, {}); | |
158 | transport = new THttpClientTransport(httpClient, config); | |
159 | } else { | |
160 | var socket = await Socket.connect(host, port); | |
161 | transport = new TClientSocketTransport(new TTcpSocket(socket)); | |
162 | if (transportType == 'framed') { | |
163 | transport = new TFramedTransport(transport); | |
164 | } | |
165 | } | |
166 | ||
167 | var protocol = protocolFactory.getProtocol(transport); | |
168 | client = new ThriftTestClient(protocol); | |
169 | ||
170 | await transport.open(); | |
171 | } | |
172 | ||
173 | List<TTest> _createTests() { | |
174 | List<TTest> tests = []; | |
175 | ||
176 | var xtruct = new Xtruct() | |
177 | ..string_thing = 'Zero' | |
178 | ..byte_thing = 1 | |
179 | ..i32_thing = -3 | |
180 | ..i64_thing = -5; | |
181 | ||
182 | tests.add(new TTest(TEST_BASETYPES, 'testVoid', () async { | |
183 | await client.testVoid(); | |
184 | })); | |
185 | ||
186 | tests.add(new TTest(TEST_BASETYPES, 'testString', () async { | |
187 | var input = 'Test'; | |
188 | var result = await client.testString(input); | |
189 | if (result != input) throw new TTestError(result, input); | |
190 | })); | |
191 | ||
192 | tests.add(new TTest(TEST_BASETYPES, 'testBool', () async { | |
193 | var input = true; | |
194 | var result = await client.testBool(input); | |
195 | if (result != input) throw new TTestError(result, input); | |
196 | })); | |
197 | ||
198 | tests.add(new TTest(TEST_BASETYPES, 'testByte', () async { | |
199 | var input = 64; | |
200 | var result = await client.testByte(input); | |
201 | if (result != input) throw new TTestError(result, input); | |
202 | })); | |
203 | ||
204 | tests.add(new TTest(TEST_BASETYPES, 'testI32', () async { | |
205 | var input = 2147483647; | |
206 | var result = await client.testI32(input); | |
207 | if (result != input) throw new TTestError(result, input); | |
208 | })); | |
209 | ||
210 | tests.add(new TTest(TEST_BASETYPES, 'testI64', () async { | |
211 | var input = 9223372036854775807; | |
212 | var result = await client.testI64(input); | |
213 | if (result != input) throw new TTestError(result, input); | |
214 | })); | |
215 | ||
216 | tests.add(new TTest(TEST_BASETYPES, 'testDouble', () async { | |
217 | var input = 3.1415926; | |
218 | var result = await client.testDouble(input); | |
219 | if (result != input) throw new TTestError(result, input); | |
220 | })); | |
221 | ||
222 | tests.add(new TTest(TEST_BASETYPES, 'testBinary', () async { | |
223 | var utf8Codec = const Utf8Codec(); | |
224 | var input = utf8Codec.encode('foo'); | |
225 | var result = await client.testBinary(input); | |
226 | var equality = const ListEquality(); | |
227 | if (!equality.equals(result, input)) throw new TTestError(result, input); | |
228 | })); | |
229 | ||
230 | tests.add(new TTest(TEST_CONTAINERS, 'testStruct', () async { | |
231 | var result = await client.testStruct(xtruct); | |
232 | if ('$result' != '$xtruct') throw new TTestError(result, xtruct); | |
233 | })); | |
234 | ||
235 | tests.add(new TTest(TEST_CONTAINERS, 'testNest', () async { | |
236 | var input = new Xtruct2() | |
237 | ..byte_thing = 1 | |
238 | ..struct_thing = xtruct | |
239 | ..i32_thing = -3; | |
240 | ||
241 | var result = await client.testNest(input); | |
242 | if ('$result' != '$input') throw new TTestError(result, input); | |
243 | })); | |
244 | ||
245 | tests.add(new TTest(TEST_CONTAINERS, 'testMap', () async { | |
246 | Map<int, int> input = {1: -10, 2: -9, 3: -8, 4: -7, 5: -6}; | |
247 | ||
248 | var result = await client.testMap(input); | |
249 | var equality = const MapEquality(); | |
250 | if (!equality.equals(result, input)) throw new TTestError(result, input); | |
251 | })); | |
252 | ||
253 | tests.add(new TTest(TEST_CONTAINERS, 'testSet', () async { | |
254 | var input = new Set<int>.from([-2, -1, 0, 1, 2]); | |
255 | var result = await client.testSet(input); | |
256 | var equality = const SetEquality(); | |
257 | if (!equality.equals(result, input)) throw new TTestError(result, input); | |
258 | })); | |
259 | ||
260 | tests.add(new TTest(TEST_CONTAINERS, 'testList', () async { | |
261 | var input = [-2, -1, 0, 1, 2]; | |
262 | var result = await client.testList(input); | |
263 | var equality = const ListEquality(); | |
264 | if (!equality.equals(result, input)) throw new TTestError(result, input); | |
265 | })); | |
266 | ||
267 | tests.add(new TTest(TEST_CONTAINERS, 'testEnum', () async { | |
268 | await _testEnum(Numberz.ONE); | |
269 | await _testEnum(Numberz.TWO); | |
270 | await _testEnum(Numberz.THREE); | |
271 | await _testEnum(Numberz.FIVE); | |
272 | await _testEnum(Numberz.EIGHT); | |
273 | })); | |
274 | ||
275 | tests.add(new TTest(TEST_BASETYPES, 'testTypedef', () async { | |
276 | var input = 309858235082523; | |
277 | var result = await client.testTypedef(input); | |
278 | if (result != input) throw new TTestError(result, input); | |
279 | })); | |
280 | ||
281 | tests.add(new TTest(TEST_CONTAINERS, 'testMapMap', () async { | |
282 | Map<int, Map<int, int>> result = await client.testMapMap(1); | |
283 | if (result.isEmpty || result[result.keys.first].isEmpty) { | |
284 | throw new TTestError(result, 'Map<int, Map<int, int>>'); | |
285 | } | |
286 | })); | |
287 | ||
288 | tests.add(new TTest(TEST_CONTAINERS, 'testInsanity', () async { | |
289 | var input = new Insanity(); | |
290 | input.userMap = {Numberz.FIVE: 5000}; | |
291 | input.xtructs = [xtruct]; | |
292 | ||
293 | Map<int, Map<int, Insanity>> result = await client.testInsanity(input); | |
294 | if (result.isEmpty || result[result.keys.first].isEmpty) { | |
295 | throw new TTestError(result, 'Map<int, Map<int, Insanity>>'); | |
296 | } | |
297 | })); | |
298 | ||
299 | tests.add(new TTest(TEST_CONTAINERS, 'testMulti', () async { | |
300 | var input = new Xtruct() | |
301 | ..string_thing = 'Hello2' | |
302 | ..byte_thing = 123 | |
303 | ..i32_thing = 456 | |
304 | ..i64_thing = 789; | |
305 | ||
306 | var result = await client.testMulti(input.byte_thing, input.i32_thing, | |
307 | input.i64_thing, {1: 'one'}, Numberz.EIGHT, 5678); | |
308 | if ('$result' != '$input') throw new TTestError(result, input); | |
309 | })); | |
310 | ||
311 | tests.add(new TTest(TEST_EXCEPTIONS, 'testException', () async { | |
312 | try { | |
313 | await client.testException('Xception'); | |
314 | } on Xception catch (_) { | |
315 | return; | |
316 | } | |
317 | ||
318 | throw new TTestError(null, 'Xception'); | |
319 | })); | |
320 | ||
321 | tests.add(new TTest(TEST_EXCEPTIONS, 'testMultiException', () async { | |
322 | try { | |
323 | await client.testMultiException('Xception2', 'foo'); | |
324 | } on Xception2 catch (_) { | |
325 | return; | |
326 | } | |
327 | ||
328 | throw new TTestError(null, 'Xception2'); | |
329 | })); | |
330 | ||
331 | return tests; | |
332 | } | |
333 | ||
334 | Future _testEnum(int input) async { | |
335 | var result = await client.testEnum(input); | |
336 | if (result != input) throw new TTestError(result, input); | |
337 | } |