blob: feba61299304aee6181d4ab82a23c531f9eae062 [file] [log] [blame]
Mark Erickson932c4702015-08-29 10:46:51 -05001/// 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 'dart:async';
19import 'dart:convert';
20import 'dart:io';
21
22import 'package:args/args.dart';
Mark Erickson56c1c642016-03-01 16:53:35 -060023import 'package:collection/collection.dart';
24import 'package:http/http.dart' as http;
Mark Erickson932c4702015-08-29 10:46:51 -050025import 'package:thrift/thrift.dart';
26import 'package:thrift/thrift_console.dart';
27import 'package:thrift_test/thrift_test.dart';
28
Mark Erickson83072a62015-10-05 14:33:28 -050029const TEST_BASETYPES = 1; // 0000 0001
30const TEST_STRUCTS = 2; // 0000 0010
31const TEST_CONTAINERS = 4; // 0000 0100
32const TEST_EXCEPTIONS = 8; // 0000 1000
33const TEST_UNKNOWN = 64; // 0100 0000 (Failed to prepare environemt etc.)
34const TEST_TIMEOUT = 128; // 1000 0000
35const TEST_NOTUSED = 48; // 0011 0000 (reserved bits)
36
37typedef Future FutureFunction();
38
39class TTest {
40 final int errorCode;
41 final String name;
42 final FutureFunction func;
43
44 TTest(this.errorCode, this.name, this.func);
45}
46
47class TTestError extends Error {
48 final actual;
49 final expected;
50
51 TTestError(this.actual, this.expected);
52
53 String toString() => '$actual != $expected';
54}
55
56List<TTest> _tests;
Mark Erickson932c4702015-08-29 10:46:51 -050057ThriftTestClient client;
58bool verbose;
59
60/// Adapted from TestClient.php
61main(List<String> args) async {
Mark Erickson83072a62015-10-05 14:33:28 -050062 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
102ArgResults _parseArgs(List<String> args) {
Mark Erickson932c4702015-08-29 10:46:51 -0500103 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',
Nobuaki Sukegawaa6ab1f52015-11-28 15:04:39 +0900108 allowed: ['buffered', 'framed', 'http'],
Mark Erickson932c4702015-08-29 10:46:51 -0500109 help: 'The transport name',
110 allowedHelp: {
111 'buffered': 'TBufferedTransport',
112 'framed': 'TFramedTransport'
113 });
114 parser.addOption('protocol',
115 defaultsTo: 'binary',
Mark Ericksonb5f126f2016-02-29 15:27:59 -0600116 allowed: ['binary', 'compact', 'json'],
Mark Erickson932c4702015-08-29 10:46:51 -0500117 help: 'The protocol name',
Mark Ericksonb5f126f2016-02-29 15:27:59 -0600118 allowedHelp: {
119 'binary': 'TBinaryProtocol',
120 'compact': 'TCompactProtocol',
121 'json': 'TJsonProtocol'
122 });
James E. King III98f379e2019-01-22 09:22:04 -0500123 parser.addFlag('verbose', defaultsTo: true);
Mark Erickson932c4702015-08-29 10:46:51 -0500124
125 ArgResults results;
126 try {
127 results = parser.parse(args);
128 } catch (e) {
129 stdout.writeln('$e\n');
Mark Erickson932c4702015-08-29 10:46:51 -0500130 }
131
Mark Erickson83072a62015-10-05 14:33:28 -0500132 if (results == null) stdout.write(parser.usage);
Mark Erickson932c4702015-08-29 10:46:51 -0500133
Mark Erickson83072a62015-10-05 14:33:28 -0500134 return results;
Mark Erickson932c4702015-08-29 10:46:51 -0500135}
136
137TProtocolFactory getProtocolFactory(String protocolType) {
138 if (protocolType == 'binary') {
139 return new TBinaryProtocolFactory();
Mark Ericksonb5f126f2016-02-29 15:27:59 -0600140 } else if (protocolType == 'compact') {
141 return new TCompactProtocolFactory();
Mark Erickson932c4702015-08-29 10:46:51 -0500142 } else if (protocolType == 'json') {
143 return new TJsonProtocolFactory();
144 }
145
146 throw new ArgumentError.value(protocolType);
147}
148
Mark Erickson83072a62015-10-05 14:33:28 -0500149Future _initTestClient(
Mark Erickson932c4702015-08-29 10:46:51 -0500150 {String host, int port, String transportType, String protocolType}) async {
151 TTransport transport;
152 var protocolFactory = getProtocolFactory(protocolType);
153
154 if (transportType == 'http') {
Mark Erickson56c1c642016-03-01 16:53:35 -0600155 var httpClient = new http.IOClient();
156 var uri = Uri.parse('http://$host:$port');
157 var config = new THttpConfig(uri, {});
Mark Erickson932c4702015-08-29 10:46:51 -0500158 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();
Mark Erickson932c4702015-08-29 10:46:51 -0500171}
172
Mark Erickson83072a62015-10-05 14:33:28 -0500173List<TTest> _createTests() {
174 List<TTest> tests = [];
Mark Erickson932c4702015-08-29 10:46:51 -0500175
Mark Erickson932c4702015-08-29 10:46:51 -0500176 var xtruct = new Xtruct()
177 ..string_thing = 'Zero'
178 ..byte_thing = 1
179 ..i32_thing = -3
180 ..i64_thing = -5;
181
Mark Erickson83072a62015-10-05 14:33:28 -0500182 tests.add(new TTest(TEST_BASETYPES, 'testVoid', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500183 await client.testVoid();
Mark Erickson83072a62015-10-05 14:33:28 -0500184 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500185
Mark Erickson83072a62015-10-05 14:33:28 -0500186 tests.add(new TTest(TEST_BASETYPES, 'testString', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500187 var input = 'Test';
188 var result = await client.testString(input);
Mark Erickson83072a62015-10-05 14:33:28 -0500189 if (result != input) throw new TTestError(result, input);
190 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500191
Mark Erickson83072a62015-10-05 14:33:28 -0500192 tests.add(new TTest(TEST_BASETYPES, 'testBool', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500193 var input = true;
194 var result = await client.testBool(input);
Mark Erickson83072a62015-10-05 14:33:28 -0500195 if (result != input) throw new TTestError(result, input);
196 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500197
Mark Erickson83072a62015-10-05 14:33:28 -0500198 tests.add(new TTest(TEST_BASETYPES, 'testByte', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500199 var input = 64;
200 var result = await client.testByte(input);
Mark Erickson83072a62015-10-05 14:33:28 -0500201 if (result != input) throw new TTestError(result, input);
202 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500203
Mark Erickson83072a62015-10-05 14:33:28 -0500204 tests.add(new TTest(TEST_BASETYPES, 'testI32', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500205 var input = 2147483647;
206 var result = await client.testI32(input);
Mark Erickson83072a62015-10-05 14:33:28 -0500207 if (result != input) throw new TTestError(result, input);
208 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500209
Mark Erickson83072a62015-10-05 14:33:28 -0500210 tests.add(new TTest(TEST_BASETYPES, 'testI64', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500211 var input = 9223372036854775807;
212 var result = await client.testI64(input);
Mark Erickson83072a62015-10-05 14:33:28 -0500213 if (result != input) throw new TTestError(result, input);
214 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500215
Mark Erickson83072a62015-10-05 14:33:28 -0500216 tests.add(new TTest(TEST_BASETYPES, 'testDouble', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500217 var input = 3.1415926;
218 var result = await client.testDouble(input);
Mark Erickson83072a62015-10-05 14:33:28 -0500219 if (result != input) throw new TTestError(result, input);
220 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500221
Mark Erickson83072a62015-10-05 14:33:28 -0500222 tests.add(new TTest(TEST_BASETYPES, 'testBinary', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500223 var utf8Codec = const Utf8Codec();
224 var input = utf8Codec.encode('foo');
225 var result = await client.testBinary(input);
226 var equality = const ListEquality();
Mark Erickson83072a62015-10-05 14:33:28 -0500227 if (!equality.equals(result, input)) throw new TTestError(result, input);
228 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500229
Mark Erickson83072a62015-10-05 14:33:28 -0500230 tests.add(new TTest(TEST_CONTAINERS, 'testStruct', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500231 var result = await client.testStruct(xtruct);
Mark Erickson83072a62015-10-05 14:33:28 -0500232 if ('$result' != '$xtruct') throw new TTestError(result, xtruct);
233 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500234
Mark Erickson83072a62015-10-05 14:33:28 -0500235 tests.add(new TTest(TEST_CONTAINERS, 'testNest', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500236 var input = new Xtruct2()
237 ..byte_thing = 1
238 ..struct_thing = xtruct
239 ..i32_thing = -3;
240
241 var result = await client.testNest(input);
Mark Erickson83072a62015-10-05 14:33:28 -0500242 if ('$result' != '$input') throw new TTestError(result, input);
243 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500244
Mark Erickson83072a62015-10-05 14:33:28 -0500245 tests.add(new TTest(TEST_CONTAINERS, 'testMap', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500246 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();
Mark Erickson83072a62015-10-05 14:33:28 -0500250 if (!equality.equals(result, input)) throw new TTestError(result, input);
251 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500252
Mark Erickson83072a62015-10-05 14:33:28 -0500253 tests.add(new TTest(TEST_CONTAINERS, 'testSet', () async {
Mark Erickson0d9b7132016-12-13 22:20:03 -0600254 var input = new Set<int>.from([-2, -1, 0, 1, 2]);
Mark Erickson932c4702015-08-29 10:46:51 -0500255 var result = await client.testSet(input);
256 var equality = const SetEquality();
Mark Erickson83072a62015-10-05 14:33:28 -0500257 if (!equality.equals(result, input)) throw new TTestError(result, input);
258 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500259
Mark Erickson83072a62015-10-05 14:33:28 -0500260 tests.add(new TTest(TEST_CONTAINERS, 'testList', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500261 var input = [-2, -1, 0, 1, 2];
262 var result = await client.testList(input);
263 var equality = const ListEquality();
Mark Erickson83072a62015-10-05 14:33:28 -0500264 if (!equality.equals(result, input)) throw new TTestError(result, input);
265 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500266
Mark Erickson83072a62015-10-05 14:33:28 -0500267 tests.add(new TTest(TEST_CONTAINERS, 'testEnum', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500268 await _testEnum(Numberz.ONE);
269 await _testEnum(Numberz.TWO);
270 await _testEnum(Numberz.THREE);
271 await _testEnum(Numberz.FIVE);
272 await _testEnum(Numberz.EIGHT);
Mark Erickson83072a62015-10-05 14:33:28 -0500273 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500274
Mark Erickson83072a62015-10-05 14:33:28 -0500275 tests.add(new TTest(TEST_BASETYPES, 'testTypedef', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500276 var input = 309858235082523;
277 var result = await client.testTypedef(input);
Mark Erickson83072a62015-10-05 14:33:28 -0500278 if (result != input) throw new TTestError(result, input);
279 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500280
Mark Erickson83072a62015-10-05 14:33:28 -0500281 tests.add(new TTest(TEST_CONTAINERS, 'testMapMap', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500282 Map<int, Map<int, int>> result = await client.testMapMap(1);
Mark Erickson83072a62015-10-05 14:33:28 -0500283 if (result.isEmpty || result[result.keys.first].isEmpty) {
284 throw new TTestError(result, 'Map<int, Map<int, int>>');
285 }
286 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500287
Mark Erickson83072a62015-10-05 14:33:28 -0500288 tests.add(new TTest(TEST_CONTAINERS, 'testInsanity', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500289 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);
Mark Erickson83072a62015-10-05 14:33:28 -0500294 if (result.isEmpty || result[result.keys.first].isEmpty) {
295 throw new TTestError(result, 'Map<int, Map<int, Insanity>>');
296 }
297 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500298
Mark Erickson83072a62015-10-05 14:33:28 -0500299 tests.add(new TTest(TEST_CONTAINERS, 'testMulti', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500300 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);
Mark Erickson83072a62015-10-05 14:33:28 -0500308 if ('$result' != '$input') throw new TTestError(result, input);
309 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500310
Mark Erickson83072a62015-10-05 14:33:28 -0500311 tests.add(new TTest(TEST_EXCEPTIONS, 'testException', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500312 try {
313 await client.testException('Xception');
Mark Erickson56c1c642016-03-01 16:53:35 -0600314 } on Xception catch (_) {
Mark Erickson932c4702015-08-29 10:46:51 -0500315 return;
316 }
317
Mark Erickson83072a62015-10-05 14:33:28 -0500318 throw new TTestError(null, 'Xception');
319 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500320
Mark Erickson83072a62015-10-05 14:33:28 -0500321 tests.add(new TTest(TEST_EXCEPTIONS, 'testMultiException', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500322 try {
323 await client.testMultiException('Xception2', 'foo');
Mark Erickson56c1c642016-03-01 16:53:35 -0600324 } on Xception2 catch (_) {
Mark Erickson932c4702015-08-29 10:46:51 -0500325 return;
326 }
327
Mark Erickson83072a62015-10-05 14:33:28 -0500328 throw new TTestError(null, 'Xception2');
329 }));
330
331 return tests;
Mark Erickson932c4702015-08-29 10:46:51 -0500332}
333
334Future _testEnum(int input) async {
335 var result = await client.testEnum(input);
Mark Erickson83072a62015-10-05 14:33:28 -0500336 if (result != input) throw new TTestError(result, input);
Mark Erickson932c4702015-08-29 10:46:51 -0500337}