blob: 4612a326a329f27ce7ef610503a048320af8eded [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
Nobuaki Sukegawaf56b9072015-11-23 19:38:18 +090053 testCases.simple.forEach(makeAsserter(function(a, e, m){
54 if (a instanceof Int64) {
55 var e64 = e instanceof Int64 ? e : new Int64(e);
56 assert.deepEqual(a.buffer, e64.buffer, m);
57 } else {
58 assert.equal(a, e, m);
59 }
Randy Abernethyd8187c52015-02-16 01:25:53 -080060 }));
61 testCases.deep.forEach(makeAsserter(assert.deepEqual));
Randy Abernethy983bf7d2015-10-09 12:28:57 -070062 testCases.deepUnordered.forEach(makeAsserter(makeUnorderedDeepEqual(assert)));
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -080063
Nobuaki Sukegawa8a4d06f2015-11-06 21:24:26 +090064 var arr = [];
65 for (var i = 0; i < 256; ++i) {
66 arr[i] = 255 - i;
67 }
68 var buf = new Buffer(arr);
69 client.testBinary(buf, function(err, response) {
70 assert.error(err, 'testBinary: no callback error');
71 assert.equal(response.length, 256, 'testBinary');
72 assert.deepEqual(response, buf, 'testBinary(Buffer)');
73 });
74 var buf = new Buffer(arr);
75 client.testBinary(buf.toString('binary'), function(err, response) {
76 assert.error(err, 'testBinary: no callback error');
77 assert.equal(response.length, 256, 'testBinary');
78 assert.deepEqual(response, buf, 'testBinary(string)');
79 });
80
Randy Abernethybd60b922015-02-26 16:59:14 -080081 client.testMapMap(42, function(err, response) {
82 var expected = {
83 "4": {"1":1, "2":2, "3":3, "4":4},
84 "-4": {"-4":-4, "-3":-3, "-2":-2, "-1":-1}
85 };
86 assert.error(err, 'testMapMap: no callback error');
87 assert.deepEqual(expected, response, 'testMapMap');
88 });
89
Randy Abernethyd8187c52015-02-16 01:25:53 -080090 client.testStruct(testCases.out, function(err, response) {
91 assert.error(err, 'testStruct: no callback error');
92 checkRecursively(testCases.out, response, 'testStruct');
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -080093 });
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -080094
Randy Abernethyd8187c52015-02-16 01:25:53 -080095 client.testNest(testCases.out2, function(err, response) {
96 assert.error(err, 'testNest: no callback error');
97 checkRecursively(testCases.out2, response, 'testNest');
98 });
99
100 client.testInsanity(testCases.crazy, function(err, response) {
101 assert.error(err, 'testInsanity: no callback error');
102 checkRecursively(testCases.insanity, response, 'testInsanity');
103 });
104
Henrique Mendonça15d90422015-06-25 22:31:41 +1000105 client.testInsanity(testCases.crazy2, function(err, response) {
106 assert.error(err, 'testInsanity2: no callback error');
107 checkRecursively(testCases.insanity, response, 'testInsanity2');
108 });
109
Randy Abernethyd8187c52015-02-16 01:25:53 -0800110 client.testException('TException', function(err, response) {
Randy Abernethybd60b922015-02-26 16:59:14 -0800111 assert.ok(err instanceof TException, 'testException: correct error type');
Randy Abernethyd8187c52015-02-16 01:25:53 -0800112 assert.ok(!response, 'testException: no response');
113 });
114
115 client.testException('Xception', function(err, response) {
Randy Abernethybd60b922015-02-26 16:59:14 -0800116 assert.ok(err instanceof ttypes.Xception, 'testException: correct error type');
Randy Abernethyd8187c52015-02-16 01:25:53 -0800117 assert.ok(!response, 'testException: no response');
118 assert.equal(err.errorCode, 1001, 'testException: correct error code');
119 assert.equal('Xception', err.message, 'testException: correct error message');
120 });
121
122 client.testException('no Exception', function(err, response) {
123 assert.error(err, 'testException: no callback error');
124 assert.ok(!response, 'testException: no response');
125 });
126
127 client.testOneway(0, function(err, response) {
bforbisf2867c22018-07-17 12:19:49 -0400128 assert.error(err, 'testOneway: no callback error');
129 assert.strictEqual(response, undefined, 'testOneway: void response');
Randy Abernethyd8187c52015-02-16 01:25:53 -0800130 });
131
132 checkOffByOne(function(done) {
133 client.testI32(-1, function(err, response) {
134 assert.error(err, 'checkOffByOne: no callback error');
135 assert.equal(-1, response);
136 assert.end();
137 done();
138 });
139 }, callback);
140
141 });
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800142};
143
144exports.ThriftTestDriverPromise = function(client, callback) {
145
Randy Abernethyd8187c52015-02-16 01:25:53 -0800146 test('Q Promise Client Tests', function(assert) {
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800147
Randy Abernethyd8187c52015-02-16 01:25:53 -0800148 var checkRecursively = makeRecursiveCheck(assert);
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800149
Randy Abernethyd8187c52015-02-16 01:25:53 -0800150 function fail(msg) {
151 return function() {
152 assert.fail(msg);
153 }
154 }
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800155
Randy Abernethyd8187c52015-02-16 01:25:53 -0800156 function makeAsserter(assertionFn) {
157 return function(c) {
158 var fnName = c[0];
159 var expected = c[1];
160 client[fnName](expected)
161 .then(function(actual) {
162 assertionFn(actual, expected, fnName);
163 })
164 .fail(fail('fnName'));
165 };
166 }
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800167
Nobuaki Sukegawaf56b9072015-11-23 19:38:18 +0900168 testCases.simple.forEach(makeAsserter(function(a, e, m){
169 if (a instanceof Int64) {
170 var e64 = e instanceof Int64 ? e : new Int64(e);
171 assert.deepEqual(a.buffer, e64.buffer, m);
172 } else {
173 assert.equal(a, e, m);
174 }
Randy Abernethyd8187c52015-02-16 01:25:53 -0800175 }));
176 testCases.deep.forEach(makeAsserter(assert.deepEqual));
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700177 testCases.deepUnordered.forEach(makeAsserter(makeUnorderedDeepEqual(assert)));
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800178
Randy Abernethyd8187c52015-02-16 01:25:53 -0800179 client.testStruct(testCases.out)
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800180 .then(function(response) {
Randy Abernethyd8187c52015-02-16 01:25:53 -0800181 checkRecursively(testCases.out, response, 'testStruct');
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800182 })
Randy Abernethyd8187c52015-02-16 01:25:53 -0800183 .fail(fail('testStruct'));
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800184
Randy Abernethyd8187c52015-02-16 01:25:53 -0800185 client.testNest(testCases.out2)
186 .then(function(response) {
187 checkRecursively(testCases.out2, response, 'testNest');
188 })
189 .fail(fail('testNest'));
190
191 client.testInsanity(testCases.crazy)
192 .then(function(response) {
193 checkRecursively(testCases.insanity, response, 'testInsanity');
194 })
195 .fail(fail('testInsanity'));
196
Henrique Mendonça15d90422015-06-25 22:31:41 +1000197 client.testInsanity(testCases.crazy2)
198 .then(function(response) {
199 checkRecursively(testCases.insanity, response, 'testInsanity2');
200 })
201 .fail(fail('testInsanity2'));
202
Randy Abernethyd8187c52015-02-16 01:25:53 -0800203 client.testException('TException')
204 .then(function(response) {
Randy Abernethybd60b922015-02-26 16:59:14 -0800205 fail('testException: TException');
Randy Abernethyd8187c52015-02-16 01:25:53 -0800206 })
Randy Abernethybd60b922015-02-26 16:59:14 -0800207 .fail(function(err) {
208 assert.ok(err instanceof TException);
209 });
Randy Abernethyd8187c52015-02-16 01:25:53 -0800210
211 client.testException('Xception')
212 .then(function(response) {
Randy Abernethybd60b922015-02-26 16:59:14 -0800213 fail('testException: Xception');
Randy Abernethyd8187c52015-02-16 01:25:53 -0800214 })
215 .fail(function(err) {
Randy Abernethybd60b922015-02-26 16:59:14 -0800216 assert.ok(err instanceof ttypes.Xception);
Randy Abernethyd8187c52015-02-16 01:25:53 -0800217 assert.equal(err.errorCode, 1001);
218 assert.equal('Xception', err.message);
219 });
220
221 client.testException('no Exception')
222 .then(function(response) {
223 assert.equal(undefined, response); //void
224 })
225 .fail(fail('testException'));
226
bforbisf2867c22018-07-17 12:19:49 -0400227 client.testOneway(0)
228 .then(function(response) {
229 assert.strictEqual(response, undefined, 'testOneway: void response')
230 })
231 .fail(fail('testOneway: should not reject'));
Randy Abernethyd8187c52015-02-16 01:25:53 -0800232
233 checkOffByOne(function(done) {
234 client.testI32(-1)
235 .then(function(response) {
236 assert.equal(-1, response);
237 assert.end();
238 done();
239 })
240 .fail(fail('checkOffByOne'));
241 }, callback);
242 });
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800243};
244
245
246// Helper Functions
247// =========================================================
248
Randy Abernethyd8187c52015-02-16 01:25:53 -0800249function makeRecursiveCheck(assert) {
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800250
Randy Abernethyd8187c52015-02-16 01:25:53 -0800251 return function (map1, map2, msg) {
252 var equal = true;
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800253
Randy Abernethyd8187c52015-02-16 01:25:53 -0800254 var equal = checkRecursively(map1, map2);
255
256 assert.ok(equal, msg);
257
258 // deepEqual doesn't work with fields using node-int64
259 function checkRecursively(map1, map2) {
260 if (typeof map1 !== 'function' && typeof map2 !== 'function') {
261 if (!map1 || typeof map1 !== 'object') {
262 //Handle int64 types (which use node-int64 in Node.js JavaScript)
263 if ((typeof map1 === "number") && (typeof map2 === "object") &&
264 (map2.buffer) && (map2.buffer instanceof Buffer) && (map2.buffer.length === 8)) {
265 var n = new Int64(map2.buffer);
266 return map1 === n.toNumber();
267 } else {
268 return map1 == map2;
269 }
270 } else {
271 return Object.keys(map1).every(function(key) {
272 return checkRecursively(map1[key], map2[key]);
273 });
274 }
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800275 }
276 }
277 }
278}
279
280function checkOffByOne(done, callback) {
281
282 var retry_limit = 30;
283 var retry_interval = 100;
284 var test_complete = false;
285 var retrys = 0;
286
287 /**
288 * redo a simple test after the oneway to make sure we aren't "off by one" --
289 * if the server treated oneway void like normal void, this next test will
290 * fail since it will get the void confirmation rather than the correct
291 * result. In this circumstance, the client will throw the exception:
292 *
293 * Because this is the last test against the server, when it completes
294 * the entire suite is complete by definition (the tests run serially).
295 */
296 done(function() {
297 test_complete = true;
298 });
299
300 //We wait up to retry_limit * retry_interval for the test suite to complete
301 function TestForCompletion() {
302 if(test_complete && callback) {
303 callback("Server successfully tested!");
304 } else {
305 if (++retrys < retry_limit) {
306 setTimeout(TestForCompletion, retry_interval);
307 } else if (callback) {
308 callback("Server test failed to complete after " +
309 (retry_limit * retry_interval / 1000) + " seconds");
310 }
311 }
312 }
313
314 setTimeout(TestForCompletion, retry_interval);
315}
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700316
317function makeUnorderedDeepEqual(assert) {
318 return function(actual, expected, name) {
319 assert.equal(actual.length, expected.length, name);
320 for (var k in actual) {
321 var found = false;
322 for (var k2 in expected) {
323 if (actual[k] === expected[k2]) {
324 found = true;
325 }
326 }
327 if (!found) {
328 assert.fail('Unexpected value ' + actual[k] + ' with key ' + k);
329 }
330 }
331 };
332}