blob: 5ad3cdee2000447ae651cc827c776586b63812ba [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';
23import 'package:collection/equality.dart';
24import 'package:thrift/thrift.dart';
25import 'package:thrift/thrift_console.dart';
26import 'package:thrift_test/thrift_test.dart';
27
Mark Erickson83072a62015-10-05 14:33:28 -050028const TEST_BASETYPES = 1; // 0000 0001
29const TEST_STRUCTS = 2; // 0000 0010
30const TEST_CONTAINERS = 4; // 0000 0100
31const TEST_EXCEPTIONS = 8; // 0000 1000
32const TEST_UNKNOWN = 64; // 0100 0000 (Failed to prepare environemt etc.)
33const TEST_TIMEOUT = 128; // 1000 0000
34const TEST_NOTUSED = 48; // 0011 0000 (reserved bits)
35
36typedef Future FutureFunction();
37
38class TTest {
39 final int errorCode;
40 final String name;
41 final FutureFunction func;
42
43 TTest(this.errorCode, this.name, this.func);
44}
45
46class TTestError extends Error {
47 final actual;
48 final expected;
49
50 TTestError(this.actual, this.expected);
51
52 String toString() => '$actual != $expected';
53}
54
55List<TTest> _tests;
Mark Erickson932c4702015-08-29 10:46:51 -050056ThriftTestClient client;
57bool verbose;
58
59/// Adapted from TestClient.php
60main(List<String> args) async {
Mark Erickson83072a62015-10-05 14:33:28 -050061 ArgResults results = _parseArgs(args);
62
63 if (results == null) {
64 exit(TEST_UNKNOWN);
65 }
66
67 verbose = results['verbose'] == true;
68
69 await _initTestClient(
70 host: results['host'],
71 port: int.parse(results['port']),
72 transportType: results['transport'],
73 protocolType: results['protocol']).catchError((e) {
74 stdout.writeln('Error:');
75 stdout.writeln('$e');
76 if (e is Error) {
77 stdout.writeln('${e.stackTrace}');
78 }
79 exit(TEST_UNKNOWN);
80 });
81
82 // run tests
83 _tests = _createTests();
84
85 int result = 0;
86
87 for (TTest test in _tests) {
88 if (verbose) stdout.write('${test.name}... ');
89 try {
90 await test.func();
91 if (verbose) stdout.writeln('success!');
92 } catch (e) {
93 if (verbose) stdout.writeln('$e');
94 result = result | test.errorCode;
95 }
96 }
97
98 exit(result);
99}
100
101ArgResults _parseArgs(List<String> args) {
Mark Erickson932c4702015-08-29 10:46:51 -0500102 var parser = new ArgParser();
103 parser.addOption('host', defaultsTo: 'localhost', help: 'The server host');
104 parser.addOption('port', defaultsTo: '9090', help: 'The port to connect to');
105 parser.addOption('transport',
106 defaultsTo: 'buffered',
Nobuaki Sukegawaa6ab1f52015-11-28 15:04:39 +0900107 allowed: ['buffered', 'framed', 'http'],
Mark Erickson932c4702015-08-29 10:46:51 -0500108 help: 'The transport name',
109 allowedHelp: {
110 'buffered': 'TBufferedTransport',
111 'framed': 'TFramedTransport'
112 });
113 parser.addOption('protocol',
114 defaultsTo: 'binary',
115 allowed: ['binary', 'json'],
116 help: 'The protocol name',
117 allowedHelp: {'binary': 'TBinaryProtocol', 'json': 'TJsonProtocol'});
118 parser.addFlag('verbose', defaultsTo: false);
119
120 ArgResults results;
121 try {
122 results = parser.parse(args);
123 } catch (e) {
124 stdout.writeln('$e\n');
Mark Erickson932c4702015-08-29 10:46:51 -0500125 }
126
Mark Erickson83072a62015-10-05 14:33:28 -0500127 if (results == null) stdout.write(parser.usage);
Mark Erickson932c4702015-08-29 10:46:51 -0500128
Mark Erickson83072a62015-10-05 14:33:28 -0500129 return results;
Mark Erickson932c4702015-08-29 10:46:51 -0500130}
131
132TProtocolFactory getProtocolFactory(String protocolType) {
133 if (protocolType == 'binary') {
134 return new TBinaryProtocolFactory();
135 } else if (protocolType == 'json') {
136 return new TJsonProtocolFactory();
137 }
138
139 throw new ArgumentError.value(protocolType);
140}
141
Mark Erickson83072a62015-10-05 14:33:28 -0500142Future _initTestClient(
Mark Erickson932c4702015-08-29 10:46:51 -0500143 {String host, int port, String transportType, String protocolType}) async {
144 TTransport transport;
145 var protocolFactory = getProtocolFactory(protocolType);
146
147 if (transportType == 'http') {
148 var httpClient = new HttpClient();
149 var config = new THttpConfig(Uri.parse('http://localhost'), {});
150 transport = new THttpClientTransport(httpClient, config);
151 } else {
152 var socket = await Socket.connect(host, port);
153 transport = new TClientSocketTransport(new TTcpSocket(socket));
154 if (transportType == 'framed') {
155 transport = new TFramedTransport(transport);
156 }
157 }
158
159 var protocol = protocolFactory.getProtocol(transport);
160 client = new ThriftTestClient(protocol);
161
162 await transport.open();
Mark Erickson932c4702015-08-29 10:46:51 -0500163}
164
Mark Erickson83072a62015-10-05 14:33:28 -0500165List<TTest> _createTests() {
166 List<TTest> tests = [];
Mark Erickson932c4702015-08-29 10:46:51 -0500167
Mark Erickson932c4702015-08-29 10:46:51 -0500168 var xtruct = new Xtruct()
169 ..string_thing = 'Zero'
170 ..byte_thing = 1
171 ..i32_thing = -3
172 ..i64_thing = -5;
173
Mark Erickson83072a62015-10-05 14:33:28 -0500174 tests.add(new TTest(TEST_BASETYPES, 'testVoid', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500175 await client.testVoid();
Mark Erickson83072a62015-10-05 14:33:28 -0500176 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500177
Mark Erickson83072a62015-10-05 14:33:28 -0500178 tests.add(new TTest(TEST_BASETYPES, 'testString', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500179 var input = 'Test';
180 var result = await client.testString(input);
Mark Erickson83072a62015-10-05 14:33:28 -0500181 if (result != input) throw new TTestError(result, input);
182 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500183
Mark Erickson83072a62015-10-05 14:33:28 -0500184 tests.add(new TTest(TEST_BASETYPES, 'testBool', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500185 var input = true;
186 var result = await client.testBool(input);
Mark Erickson83072a62015-10-05 14:33:28 -0500187 if (result != input) throw new TTestError(result, input);
188 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500189
Mark Erickson83072a62015-10-05 14:33:28 -0500190 tests.add(new TTest(TEST_BASETYPES, 'testByte', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500191 var input = 64;
192 var result = await client.testByte(input);
Mark Erickson83072a62015-10-05 14:33:28 -0500193 if (result != input) throw new TTestError(result, input);
194 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500195
Mark Erickson83072a62015-10-05 14:33:28 -0500196 tests.add(new TTest(TEST_BASETYPES, 'testI32', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500197 var input = 2147483647;
198 var result = await client.testI32(input);
Mark Erickson83072a62015-10-05 14:33:28 -0500199 if (result != input) throw new TTestError(result, input);
200 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500201
Mark Erickson83072a62015-10-05 14:33:28 -0500202 tests.add(new TTest(TEST_BASETYPES, 'testI64', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500203 var input = 9223372036854775807;
204 var result = await client.testI64(input);
Mark Erickson83072a62015-10-05 14:33:28 -0500205 if (result != input) throw new TTestError(result, input);
206 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500207
Mark Erickson83072a62015-10-05 14:33:28 -0500208 tests.add(new TTest(TEST_BASETYPES, 'testDouble', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500209 var input = 3.1415926;
210 var result = await client.testDouble(input);
Mark Erickson83072a62015-10-05 14:33:28 -0500211 if (result != input) throw new TTestError(result, input);
212 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500213
Mark Erickson83072a62015-10-05 14:33:28 -0500214 tests.add(new TTest(TEST_BASETYPES, 'testBinary', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500215 var utf8Codec = const Utf8Codec();
216 var input = utf8Codec.encode('foo');
217 var result = await client.testBinary(input);
218 var equality = const ListEquality();
Mark Erickson83072a62015-10-05 14:33:28 -0500219 if (!equality.equals(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_CONTAINERS, 'testStruct', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500223 var result = await client.testStruct(xtruct);
Mark Erickson83072a62015-10-05 14:33:28 -0500224 if ('$result' != '$xtruct') throw new TTestError(result, xtruct);
225 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500226
Mark Erickson83072a62015-10-05 14:33:28 -0500227 tests.add(new TTest(TEST_CONTAINERS, 'testNest', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500228 var input = new Xtruct2()
229 ..byte_thing = 1
230 ..struct_thing = xtruct
231 ..i32_thing = -3;
232
233 var result = await client.testNest(input);
Mark Erickson83072a62015-10-05 14:33:28 -0500234 if ('$result' != '$input') throw new TTestError(result, input);
235 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500236
Mark Erickson83072a62015-10-05 14:33:28 -0500237 tests.add(new TTest(TEST_CONTAINERS, 'testMap', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500238 Map<int, int> input = {1: -10, 2: -9, 3: -8, 4: -7, 5: -6};
239
240 var result = await client.testMap(input);
241 var equality = const MapEquality();
Mark Erickson83072a62015-10-05 14:33:28 -0500242 if (!equality.equals(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, 'testSet', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500246 var input = new Set.from([-2, -1, 0, 1, 2]);
247 var result = await client.testSet(input);
248 var equality = const SetEquality();
Mark Erickson83072a62015-10-05 14:33:28 -0500249 if (!equality.equals(result, input)) throw new TTestError(result, input);
250 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500251
Mark Erickson83072a62015-10-05 14:33:28 -0500252 tests.add(new TTest(TEST_CONTAINERS, 'testList', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500253 var input = [-2, -1, 0, 1, 2];
254 var result = await client.testList(input);
255 var equality = const ListEquality();
Mark Erickson83072a62015-10-05 14:33:28 -0500256 if (!equality.equals(result, input)) throw new TTestError(result, input);
257 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500258
Mark Erickson83072a62015-10-05 14:33:28 -0500259 tests.add(new TTest(TEST_CONTAINERS, 'testEnum', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500260 await _testEnum(Numberz.ONE);
261 await _testEnum(Numberz.TWO);
262 await _testEnum(Numberz.THREE);
263 await _testEnum(Numberz.FIVE);
264 await _testEnum(Numberz.EIGHT);
Mark Erickson83072a62015-10-05 14:33:28 -0500265 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500266
Mark Erickson83072a62015-10-05 14:33:28 -0500267 tests.add(new TTest(TEST_BASETYPES, 'testTypedef', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500268 var input = 309858235082523;
269 var result = await client.testTypedef(input);
Mark Erickson83072a62015-10-05 14:33:28 -0500270 if (result != input) throw new TTestError(result, input);
271 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500272
Mark Erickson83072a62015-10-05 14:33:28 -0500273 tests.add(new TTest(TEST_CONTAINERS, 'testMapMap', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500274 Map<int, Map<int, int>> result = await client.testMapMap(1);
Mark Erickson83072a62015-10-05 14:33:28 -0500275 if (result.isEmpty || result[result.keys.first].isEmpty) {
276 throw new TTestError(result, 'Map<int, Map<int, int>>');
277 }
278 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500279
Mark Erickson83072a62015-10-05 14:33:28 -0500280 tests.add(new TTest(TEST_CONTAINERS, 'testInsanity', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500281 var input = new Insanity();
282 input.userMap = {Numberz.FIVE: 5000};
283 input.xtructs = [xtruct];
284
285 Map<int, Map<int, Insanity>> result = await client.testInsanity(input);
Mark Erickson83072a62015-10-05 14:33:28 -0500286 if (result.isEmpty || result[result.keys.first].isEmpty) {
287 throw new TTestError(result, 'Map<int, Map<int, Insanity>>');
288 }
289 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500290
Mark Erickson83072a62015-10-05 14:33:28 -0500291 tests.add(new TTest(TEST_CONTAINERS, 'testMulti', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500292 var input = new Xtruct()
293 ..string_thing = 'Hello2'
294 ..byte_thing = 123
295 ..i32_thing = 456
296 ..i64_thing = 789;
297
298 var result = await client.testMulti(input.byte_thing, input.i32_thing,
299 input.i64_thing, {1: 'one'}, Numberz.EIGHT, 5678);
Mark Erickson83072a62015-10-05 14:33:28 -0500300 if ('$result' != '$input') throw new TTestError(result, input);
301 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500302
Mark Erickson83072a62015-10-05 14:33:28 -0500303 tests.add(new TTest(TEST_EXCEPTIONS, 'testException', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500304 try {
305 await client.testException('Xception');
306 } on Xception catch (x) {
307 return;
308 }
309
Mark Erickson83072a62015-10-05 14:33:28 -0500310 throw new TTestError(null, 'Xception');
311 }));
Mark Erickson932c4702015-08-29 10:46:51 -0500312
Mark Erickson83072a62015-10-05 14:33:28 -0500313 tests.add(new TTest(TEST_EXCEPTIONS, 'testMultiException', () async {
Mark Erickson932c4702015-08-29 10:46:51 -0500314 try {
315 await client.testMultiException('Xception2', 'foo');
316 } on Xception2 catch (x) {
317 return;
318 }
319
Mark Erickson83072a62015-10-05 14:33:28 -0500320 throw new TTestError(null, 'Xception2');
321 }));
322
323 return tests;
Mark Erickson932c4702015-08-29 10:46:51 -0500324}
325
326Future _testEnum(int input) async {
327 var result = await client.testEnum(input);
Mark Erickson83072a62015-10-05 14:33:28 -0500328 if (result != input) throw new TTestError(result, input);
Mark Erickson932c4702015-08-29 10:46:51 -0500329}