blob: 09439e55ccb6de6de11b1f97aa8d35729d82aade [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
Randy Abernethybd60b922015-02-26 16:59:14 -080060 client.testMapMap(42, function(err, response) {
61 var expected = {
62 "4": {"1":1, "2":2, "3":3, "4":4},
63 "-4": {"-4":-4, "-3":-3, "-2":-2, "-1":-1}
64 };
65 assert.error(err, 'testMapMap: no callback error');
66 assert.deepEqual(expected, response, 'testMapMap');
67 });
68
Randy Abernethyd8187c52015-02-16 01:25:53 -080069 client.testStruct(testCases.out, function(err, response) {
70 assert.error(err, 'testStruct: no callback error');
71 checkRecursively(testCases.out, response, 'testStruct');
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -080072 });
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -080073
Randy Abernethyd8187c52015-02-16 01:25:53 -080074 client.testNest(testCases.out2, function(err, response) {
75 assert.error(err, 'testNest: no callback error');
76 checkRecursively(testCases.out2, response, 'testNest');
77 });
78
79 client.testInsanity(testCases.crazy, function(err, response) {
80 assert.error(err, 'testInsanity: no callback error');
81 checkRecursively(testCases.insanity, response, 'testInsanity');
82 });
83
Henrique Mendonça15d90422015-06-25 22:31:41 +100084 client.testInsanity(testCases.crazy2, function(err, response) {
85 assert.error(err, 'testInsanity2: no callback error');
86 checkRecursively(testCases.insanity, response, 'testInsanity2');
87 });
88
Randy Abernethyd8187c52015-02-16 01:25:53 -080089 client.testException('TException', function(err, response) {
Randy Abernethybd60b922015-02-26 16:59:14 -080090 assert.ok(err instanceof TException, 'testException: correct error type');
Randy Abernethyd8187c52015-02-16 01:25:53 -080091 assert.ok(!response, 'testException: no response');
92 });
93
94 client.testException('Xception', function(err, response) {
Randy Abernethybd60b922015-02-26 16:59:14 -080095 assert.ok(err instanceof ttypes.Xception, 'testException: correct error type');
Randy Abernethyd8187c52015-02-16 01:25:53 -080096 assert.ok(!response, 'testException: no response');
97 assert.equal(err.errorCode, 1001, 'testException: correct error code');
98 assert.equal('Xception', err.message, 'testException: correct error message');
99 });
100
101 client.testException('no Exception', function(err, response) {
102 assert.error(err, 'testException: no callback error');
103 assert.ok(!response, 'testException: no response');
104 });
105
106 client.testOneway(0, function(err, response) {
107 assert.fail('testOneway should not answer');
108 });
109
110 checkOffByOne(function(done) {
111 client.testI32(-1, function(err, response) {
112 assert.error(err, 'checkOffByOne: no callback error');
113 assert.equal(-1, response);
114 assert.end();
115 done();
116 });
117 }, callback);
118
119 });
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800120};
121
122exports.ThriftTestDriverPromise = function(client, callback) {
123
Randy Abernethyd8187c52015-02-16 01:25:53 -0800124 test('Q Promise Client Tests', function(assert) {
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800125
Randy Abernethyd8187c52015-02-16 01:25:53 -0800126 var checkRecursively = makeRecursiveCheck(assert);
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800127
Randy Abernethyd8187c52015-02-16 01:25:53 -0800128 function fail(msg) {
129 return function() {
130 assert.fail(msg);
131 }
132 }
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800133
Randy Abernethyd8187c52015-02-16 01:25:53 -0800134 function makeAsserter(assertionFn) {
135 return function(c) {
136 var fnName = c[0];
137 var expected = c[1];
138 client[fnName](expected)
139 .then(function(actual) {
140 assertionFn(actual, expected, fnName);
141 })
142 .fail(fail('fnName'));
143 };
144 }
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800145
Randy Abernethyd8187c52015-02-16 01:25:53 -0800146 testCases.simple.forEach(makeAsserter(assert.equal));
147 testCases.simpleLoose.forEach(makeAsserter(function(a, e, m){
148 assert.ok(a == e, m);
149 }));
150 testCases.deep.forEach(makeAsserter(assert.deepEqual));
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700151 testCases.deepUnordered.forEach(makeAsserter(makeUnorderedDeepEqual(assert)));
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800152
Randy Abernethyd8187c52015-02-16 01:25:53 -0800153 client.testStruct(testCases.out)
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800154 .then(function(response) {
Randy Abernethyd8187c52015-02-16 01:25:53 -0800155 checkRecursively(testCases.out, response, 'testStruct');
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800156 })
Randy Abernethyd8187c52015-02-16 01:25:53 -0800157 .fail(fail('testStruct'));
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800158
Randy Abernethyd8187c52015-02-16 01:25:53 -0800159 client.testNest(testCases.out2)
160 .then(function(response) {
161 checkRecursively(testCases.out2, response, 'testNest');
162 })
163 .fail(fail('testNest'));
164
165 client.testInsanity(testCases.crazy)
166 .then(function(response) {
167 checkRecursively(testCases.insanity, response, 'testInsanity');
168 })
169 .fail(fail('testInsanity'));
170
Henrique Mendonça15d90422015-06-25 22:31:41 +1000171 client.testInsanity(testCases.crazy2)
172 .then(function(response) {
173 checkRecursively(testCases.insanity, response, 'testInsanity2');
174 })
175 .fail(fail('testInsanity2'));
176
Randy Abernethyd8187c52015-02-16 01:25:53 -0800177 client.testException('TException')
178 .then(function(response) {
Randy Abernethybd60b922015-02-26 16:59:14 -0800179 fail('testException: TException');
Randy Abernethyd8187c52015-02-16 01:25:53 -0800180 })
Randy Abernethybd60b922015-02-26 16:59:14 -0800181 .fail(function(err) {
182 assert.ok(err instanceof TException);
183 });
Randy Abernethyd8187c52015-02-16 01:25:53 -0800184
185 client.testException('Xception')
186 .then(function(response) {
Randy Abernethybd60b922015-02-26 16:59:14 -0800187 fail('testException: Xception');
Randy Abernethyd8187c52015-02-16 01:25:53 -0800188 })
189 .fail(function(err) {
Randy Abernethybd60b922015-02-26 16:59:14 -0800190 assert.ok(err instanceof ttypes.Xception);
Randy Abernethyd8187c52015-02-16 01:25:53 -0800191 assert.equal(err.errorCode, 1001);
192 assert.equal('Xception', err.message);
193 });
194
195 client.testException('no Exception')
196 .then(function(response) {
197 assert.equal(undefined, response); //void
198 })
199 .fail(fail('testException'));
200
201 client.testOneway(0, fail('testOneway: should not answer'));
202
203 checkOffByOne(function(done) {
204 client.testI32(-1)
205 .then(function(response) {
206 assert.equal(-1, response);
207 assert.end();
208 done();
209 })
210 .fail(fail('checkOffByOne'));
211 }, callback);
212 });
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800213};
214
215
216// Helper Functions
217// =========================================================
218
Randy Abernethyd8187c52015-02-16 01:25:53 -0800219function makeRecursiveCheck(assert) {
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800220
Randy Abernethyd8187c52015-02-16 01:25:53 -0800221 return function (map1, map2, msg) {
222 var equal = true;
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800223
Randy Abernethyd8187c52015-02-16 01:25:53 -0800224 var equal = checkRecursively(map1, map2);
225
226 assert.ok(equal, msg);
227
228 // deepEqual doesn't work with fields using node-int64
229 function checkRecursively(map1, map2) {
230 if (typeof map1 !== 'function' && typeof map2 !== 'function') {
231 if (!map1 || typeof map1 !== 'object') {
232 //Handle int64 types (which use node-int64 in Node.js JavaScript)
233 if ((typeof map1 === "number") && (typeof map2 === "object") &&
234 (map2.buffer) && (map2.buffer instanceof Buffer) && (map2.buffer.length === 8)) {
235 var n = new Int64(map2.buffer);
236 return map1 === n.toNumber();
237 } else {
238 return map1 == map2;
239 }
240 } else {
241 return Object.keys(map1).every(function(key) {
242 return checkRecursively(map1[key], map2[key]);
243 });
244 }
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800245 }
246 }
247 }
248}
249
250function checkOffByOne(done, callback) {
251
252 var retry_limit = 30;
253 var retry_interval = 100;
254 var test_complete = false;
255 var retrys = 0;
256
257 /**
258 * redo a simple test after the oneway to make sure we aren't "off by one" --
259 * if the server treated oneway void like normal void, this next test will
260 * fail since it will get the void confirmation rather than the correct
261 * result. In this circumstance, the client will throw the exception:
262 *
263 * Because this is the last test against the server, when it completes
264 * the entire suite is complete by definition (the tests run serially).
265 */
266 done(function() {
267 test_complete = true;
268 });
269
270 //We wait up to retry_limit * retry_interval for the test suite to complete
271 function TestForCompletion() {
272 if(test_complete && callback) {
273 callback("Server successfully tested!");
274 } else {
275 if (++retrys < retry_limit) {
276 setTimeout(TestForCompletion, retry_interval);
277 } else if (callback) {
278 callback("Server test failed to complete after " +
279 (retry_limit * retry_interval / 1000) + " seconds");
280 }
281 }
282 }
283
284 setTimeout(TestForCompletion, retry_interval);
285}
Randy Abernethy983bf7d2015-10-09 12:28:57 -0700286
287function makeUnorderedDeepEqual(assert) {
288 return function(actual, expected, name) {
289 assert.equal(actual.length, expected.length, name);
290 for (var k in actual) {
291 var found = false;
292 for (var k2 in expected) {
293 if (actual[k] === expected[k2]) {
294 found = true;
295 }
296 }
297 if (!found) {
298 assert.fail('Unexpected value ' + actual[k] + ' with key ' + k);
299 }
300 }
301 };
302}