blob: 590d5833743209114f8ced4244f68a5866e74c48 [file] [log] [blame]
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -08001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * 'License'); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20 // This is the Node.js test driver for the standard Apache Thrift
21 // test service. The driver invokes every function defined in the
22 // Thrift Test service with a representative range of parameters.
23 //
24 // The ThriftTestDriver function requires a client object
25 // connected to a server hosting the Thrift Test service and
26 // supports an optional callback function which is called with
27 // a status message when the test is complete.
28
Randy Abernethyd8187c52015-02-16 01:25:53 -080029var test = require('tape');
30//var assert = require('assert');
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -080031var ttypes = require('./gen-nodejs/ThriftTest_types');
Randy Abernethybd60b922015-02-26 16:59:14 -080032var TException = require('thrift').Thrift.TException;
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -080033var Int64 = require('node-int64');
34var testCases = require('./test-cases');
35
36exports.ThriftTestDriver = function(client, callback) {
37
Randy Abernethyd8187c52015-02-16 01:25:53 -080038 test('NodeJS Style Callback Client Tests', function(assert) {
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -080039
Randy Abernethyd8187c52015-02-16 01:25:53 -080040 var checkRecursively = makeRecursiveCheck(assert);
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -080041
Randy Abernethyd8187c52015-02-16 01:25:53 -080042 function makeAsserter(assertionFn) {
43 return function(c) {
44 var fnName = c[0];
45 var expected = c[1];
46 client[fnName](expected, function(err, actual) {
47 assert.error(err, fnName + ': no callback error');
48 assertionFn(actual, expected, fnName);
49 })
50 };
51 }
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -080052
Randy Abernethyd8187c52015-02-16 01:25:53 -080053 testCases.simple.forEach(makeAsserter(assert.equal));
54 testCases.simpleLoose.forEach(makeAsserter(function(a, e, m){
55 assert.ok(a == e, m);
56 }));
57 testCases.deep.forEach(makeAsserter(assert.deepEqual));
Randy Abernethy983bf7d2015-10-09 12:28:57 -070058 testCases.deepUnordered.forEach(makeAsserter(makeUnorderedDeepEqual(assert)));
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -080059
Nobuaki Sukegawa8a4d06f2015-11-06 21:24:26 +090060 var arr = [];
61 for (var i = 0; i < 256; ++i) {
62 arr[i] = 255 - i;
63 }
64 var buf = new Buffer(arr);
65 client.testBinary(buf, function(err, response) {
66 assert.error(err, 'testBinary: no callback error');
67 assert.equal(response.length, 256, 'testBinary');
68 assert.deepEqual(response, buf, 'testBinary(Buffer)');
69 });
70 var buf = new Buffer(arr);
71 client.testBinary(buf.toString('binary'), function(err, response) {
72 assert.error(err, 'testBinary: no callback error');
73 assert.equal(response.length, 256, 'testBinary');
74 assert.deepEqual(response, buf, 'testBinary(string)');
75 });
76
Randy Abernethybd60b922015-02-26 16:59:14 -080077 client.testMapMap(42, function(err, response) {
78 var expected = {
79 "4": {"1":1, "2":2, "3":3, "4":4},
80 "-4": {"-4":-4, "-3":-3, "-2":-2, "-1":-1}
81 };
82 assert.error(err, 'testMapMap: no callback error');
83 assert.deepEqual(expected, response, 'testMapMap');
84 });
85
Randy Abernethyd8187c52015-02-16 01:25:53 -080086 client.testStruct(testCases.out, function(err, response) {
87 assert.error(err, 'testStruct: no callback error');
88 checkRecursively(testCases.out, response, 'testStruct');
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -080089 });
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -080090
Randy Abernethyd8187c52015-02-16 01:25:53 -080091 client.testNest(testCases.out2, function(err, response) {
92 assert.error(err, 'testNest: no callback error');
93 checkRecursively(testCases.out2, response, 'testNest');
94 });
95
96 client.testInsanity(testCases.crazy, function(err, response) {
97 assert.error(err, 'testInsanity: no callback error');
98 checkRecursively(testCases.insanity, response, 'testInsanity');
99 });
100
Henrique Mendonça15d90422015-06-25 22:31:41 +1000101 client.testInsanity(testCases.crazy2, function(err, response) {
102 assert.error(err, 'testInsanity2: no callback error');
103 checkRecursively(testCases.insanity, response, 'testInsanity2');
104 });
105
Randy Abernethyd8187c52015-02-16 01:25:53 -0800106 client.testException('TException', function(err, response) {
Randy Abernethybd60b922015-02-26 16:59:14 -0800107 assert.ok(err instanceof TException, 'testException: correct error type');
Randy Abernethyd8187c52015-02-16 01:25:53 -0800108 assert.ok(!response, 'testException: no response');
109 });
110
111 client.testException('Xception', function(err, response) {
Randy Abernethybd60b922015-02-26 16:59:14 -0800112 assert.ok(err instanceof ttypes.Xception, 'testException: correct error type');
Randy Abernethyd8187c52015-02-16 01:25:53 -0800113 assert.ok(!response, 'testException: no response');
114 assert.equal(err.errorCode, 1001, 'testException: correct error code');
115 assert.equal('Xception', err.message, 'testException: correct error message');
116 });
117
118 client.testException('no Exception', function(err, response) {
119 assert.error(err, 'testException: no callback error');
120 assert.ok(!response, 'testException: no response');
121 });
122
123 client.testOneway(0, function(err, response) {
124 assert.fail('testOneway should not answer');
125 });
126
127 checkOffByOne(function(done) {
128 client.testI32(-1, function(err, response) {
129 assert.error(err, 'checkOffByOne: no callback error');
130 assert.equal(-1, response);
131 assert.end();
132 done();
133 });
134 }, callback);
135
136 });
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800137};
138
139exports.ThriftTestDriverPromise = function(client, callback) {
140
Randy Abernethyd8187c52015-02-16 01:25:53 -0800141 test('Q Promise Client Tests', function(assert) {
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800142
Randy Abernethyd8187c52015-02-16 01:25:53 -0800143 var checkRecursively = makeRecursiveCheck(assert);
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800144
Randy Abernethyd8187c52015-02-16 01:25:53 -0800145 function fail(msg) {
146 return function() {
147 assert.fail(msg);
148 }
149 }
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800150
Randy Abernethyd8187c52015-02-16 01:25:53 -0800151 function makeAsserter(assertionFn) {
152 return function(c) {
153 var fnName = c[0];
154 var expected = c[1];
155 client[fnName](expected)
156 .then(function(actual) {
157 assertionFn(actual, expected, fnName);
158 })
159 .fail(fail('fnName'));
160 };
161 }
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800162
Randy Abernethyd8187c52015-02-16 01:25:53 -0800163 testCases.simple.forEach(makeAsserter(assert.equal));
164 testCases.simpleLoose.forEach(makeAsserter(function(a, e, m){
165 assert.ok(a == e, m);
166 }));
167 testCases.deep.forEach(makeAsserter(assert.deepEqual));
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700168 testCases.deepUnordered.forEach(makeAsserter(makeUnorderedDeepEqual(assert)));
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800169
Randy Abernethyd8187c52015-02-16 01:25:53 -0800170 client.testStruct(testCases.out)
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800171 .then(function(response) {
Randy Abernethyd8187c52015-02-16 01:25:53 -0800172 checkRecursively(testCases.out, response, 'testStruct');
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800173 })
Randy Abernethyd8187c52015-02-16 01:25:53 -0800174 .fail(fail('testStruct'));
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800175
Randy Abernethyd8187c52015-02-16 01:25:53 -0800176 client.testNest(testCases.out2)
177 .then(function(response) {
178 checkRecursively(testCases.out2, response, 'testNest');
179 })
180 .fail(fail('testNest'));
181
182 client.testInsanity(testCases.crazy)
183 .then(function(response) {
184 checkRecursively(testCases.insanity, response, 'testInsanity');
185 })
186 .fail(fail('testInsanity'));
187
Henrique Mendonça15d90422015-06-25 22:31:41 +1000188 client.testInsanity(testCases.crazy2)
189 .then(function(response) {
190 checkRecursively(testCases.insanity, response, 'testInsanity2');
191 })
192 .fail(fail('testInsanity2'));
193
Randy Abernethyd8187c52015-02-16 01:25:53 -0800194 client.testException('TException')
195 .then(function(response) {
Randy Abernethybd60b922015-02-26 16:59:14 -0800196 fail('testException: TException');
Randy Abernethyd8187c52015-02-16 01:25:53 -0800197 })
Randy Abernethybd60b922015-02-26 16:59:14 -0800198 .fail(function(err) {
199 assert.ok(err instanceof TException);
200 });
Randy Abernethyd8187c52015-02-16 01:25:53 -0800201
202 client.testException('Xception')
203 .then(function(response) {
Randy Abernethybd60b922015-02-26 16:59:14 -0800204 fail('testException: Xception');
Randy Abernethyd8187c52015-02-16 01:25:53 -0800205 })
206 .fail(function(err) {
Randy Abernethybd60b922015-02-26 16:59:14 -0800207 assert.ok(err instanceof ttypes.Xception);
Randy Abernethyd8187c52015-02-16 01:25:53 -0800208 assert.equal(err.errorCode, 1001);
209 assert.equal('Xception', err.message);
210 });
211
212 client.testException('no Exception')
213 .then(function(response) {
214 assert.equal(undefined, response); //void
215 })
216 .fail(fail('testException'));
217
218 client.testOneway(0, fail('testOneway: should not answer'));
219
220 checkOffByOne(function(done) {
221 client.testI32(-1)
222 .then(function(response) {
223 assert.equal(-1, response);
224 assert.end();
225 done();
226 })
227 .fail(fail('checkOffByOne'));
228 }, callback);
229 });
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800230};
231
232
233// Helper Functions
234// =========================================================
235
Randy Abernethyd8187c52015-02-16 01:25:53 -0800236function makeRecursiveCheck(assert) {
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800237
Randy Abernethyd8187c52015-02-16 01:25:53 -0800238 return function (map1, map2, msg) {
239 var equal = true;
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800240
Randy Abernethyd8187c52015-02-16 01:25:53 -0800241 var equal = checkRecursively(map1, map2);
242
243 assert.ok(equal, msg);
244
245 // deepEqual doesn't work with fields using node-int64
246 function checkRecursively(map1, map2) {
247 if (typeof map1 !== 'function' && typeof map2 !== 'function') {
248 if (!map1 || typeof map1 !== 'object') {
249 //Handle int64 types (which use node-int64 in Node.js JavaScript)
250 if ((typeof map1 === "number") && (typeof map2 === "object") &&
251 (map2.buffer) && (map2.buffer instanceof Buffer) && (map2.buffer.length === 8)) {
252 var n = new Int64(map2.buffer);
253 return map1 === n.toNumber();
254 } else {
255 return map1 == map2;
256 }
257 } else {
258 return Object.keys(map1).every(function(key) {
259 return checkRecursively(map1[key], map2[key]);
260 });
261 }
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800262 }
263 }
264 }
265}
266
267function checkOffByOne(done, callback) {
268
269 var retry_limit = 30;
270 var retry_interval = 100;
271 var test_complete = false;
272 var retrys = 0;
273
274 /**
275 * redo a simple test after the oneway to make sure we aren't "off by one" --
276 * if the server treated oneway void like normal void, this next test will
277 * fail since it will get the void confirmation rather than the correct
278 * result. In this circumstance, the client will throw the exception:
279 *
280 * Because this is the last test against the server, when it completes
281 * the entire suite is complete by definition (the tests run serially).
282 */
283 done(function() {
284 test_complete = true;
285 });
286
287 //We wait up to retry_limit * retry_interval for the test suite to complete
288 function TestForCompletion() {
289 if(test_complete && callback) {
290 callback("Server successfully tested!");
291 } else {
292 if (++retrys < retry_limit) {
293 setTimeout(TestForCompletion, retry_interval);
294 } else if (callback) {
295 callback("Server test failed to complete after " +
296 (retry_limit * retry_interval / 1000) + " seconds");
297 }
298 }
299 }
300
301 setTimeout(TestForCompletion, retry_interval);
302}
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700303
304function makeUnorderedDeepEqual(assert) {
305 return function(actual, expected, name) {
306 assert.equal(actual.length, expected.length, name);
307 for (var k in actual) {
308 var found = false;
309 for (var k2 in expected) {
310 if (actual[k] === expected[k2]) {
311 found = true;
312 }
313 }
314 if (!found) {
315 assert.fail('Unexpected value ' + actual[k] + ' with key ' + k);
316 }
317 }
318 };
319}