blob: 27ffd63ecaa2458f1ddf739935a37e52236b8370 [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 Abernethy3b9ff4d2015-02-16 00:51:24 -080058
Randy Abernethybd60b922015-02-26 16:59:14 -080059 client.testMapMap(42, function(err, response) {
60 var expected = {
61 "4": {"1":1, "2":2, "3":3, "4":4},
62 "-4": {"-4":-4, "-3":-3, "-2":-2, "-1":-1}
63 };
64 assert.error(err, 'testMapMap: no callback error');
65 assert.deepEqual(expected, response, 'testMapMap');
66 });
67
Randy Abernethyd8187c52015-02-16 01:25:53 -080068 client.testStruct(testCases.out, function(err, response) {
69 assert.error(err, 'testStruct: no callback error');
70 checkRecursively(testCases.out, response, 'testStruct');
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -080071 });
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -080072
Randy Abernethyd8187c52015-02-16 01:25:53 -080073 client.testNest(testCases.out2, function(err, response) {
74 assert.error(err, 'testNest: no callback error');
75 checkRecursively(testCases.out2, response, 'testNest');
76 });
77
78 client.testInsanity(testCases.crazy, function(err, response) {
79 assert.error(err, 'testInsanity: no callback error');
80 checkRecursively(testCases.insanity, response, 'testInsanity');
81 });
82
Henrique Mendonça15d90422015-06-25 22:31:41 +100083 client.testInsanity(testCases.crazy2, function(err, response) {
84 assert.error(err, 'testInsanity2: no callback error');
85 checkRecursively(testCases.insanity, response, 'testInsanity2');
86 });
87
Randy Abernethyd8187c52015-02-16 01:25:53 -080088 client.testException('TException', function(err, response) {
Randy Abernethybd60b922015-02-26 16:59:14 -080089 assert.ok(err instanceof TException, 'testException: correct error type');
Randy Abernethyd8187c52015-02-16 01:25:53 -080090 assert.ok(!response, 'testException: no response');
91 });
92
93 client.testException('Xception', function(err, response) {
Randy Abernethybd60b922015-02-26 16:59:14 -080094 assert.ok(err instanceof ttypes.Xception, 'testException: correct error type');
Randy Abernethyd8187c52015-02-16 01:25:53 -080095 assert.ok(!response, 'testException: no response');
96 assert.equal(err.errorCode, 1001, 'testException: correct error code');
97 assert.equal('Xception', err.message, 'testException: correct error message');
98 });
99
100 client.testException('no Exception', function(err, response) {
101 assert.error(err, 'testException: no callback error');
102 assert.ok(!response, 'testException: no response');
103 });
104
105 client.testOneway(0, function(err, response) {
106 assert.fail('testOneway should not answer');
107 });
108
109 checkOffByOne(function(done) {
110 client.testI32(-1, function(err, response) {
111 assert.error(err, 'checkOffByOne: no callback error');
112 assert.equal(-1, response);
113 assert.end();
114 done();
115 });
116 }, callback);
117
118 });
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800119};
120
121exports.ThriftTestDriverPromise = function(client, callback) {
122
Randy Abernethyd8187c52015-02-16 01:25:53 -0800123 test('Q Promise Client Tests', function(assert) {
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800124
Randy Abernethyd8187c52015-02-16 01:25:53 -0800125 var checkRecursively = makeRecursiveCheck(assert);
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800126
Randy Abernethyd8187c52015-02-16 01:25:53 -0800127 function fail(msg) {
128 return function() {
129 assert.fail(msg);
130 }
131 }
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800132
Randy Abernethyd8187c52015-02-16 01:25:53 -0800133 function makeAsserter(assertionFn) {
134 return function(c) {
135 var fnName = c[0];
136 var expected = c[1];
137 client[fnName](expected)
138 .then(function(actual) {
139 assertionFn(actual, expected, fnName);
140 })
141 .fail(fail('fnName'));
142 };
143 }
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800144
Randy Abernethyd8187c52015-02-16 01:25:53 -0800145 testCases.simple.forEach(makeAsserter(assert.equal));
146 testCases.simpleLoose.forEach(makeAsserter(function(a, e, m){
147 assert.ok(a == e, m);
148 }));
149 testCases.deep.forEach(makeAsserter(assert.deepEqual));
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800150
Randy Abernethyd8187c52015-02-16 01:25:53 -0800151 client.testStruct(testCases.out)
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800152 .then(function(response) {
Randy Abernethyd8187c52015-02-16 01:25:53 -0800153 checkRecursively(testCases.out, response, 'testStruct');
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800154 })
Randy Abernethyd8187c52015-02-16 01:25:53 -0800155 .fail(fail('testStruct'));
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800156
Randy Abernethyd8187c52015-02-16 01:25:53 -0800157 client.testNest(testCases.out2)
158 .then(function(response) {
159 checkRecursively(testCases.out2, response, 'testNest');
160 })
161 .fail(fail('testNest'));
162
163 client.testInsanity(testCases.crazy)
164 .then(function(response) {
165 checkRecursively(testCases.insanity, response, 'testInsanity');
166 })
167 .fail(fail('testInsanity'));
168
Henrique Mendonça15d90422015-06-25 22:31:41 +1000169 client.testInsanity(testCases.crazy2)
170 .then(function(response) {
171 checkRecursively(testCases.insanity, response, 'testInsanity2');
172 })
173 .fail(fail('testInsanity2'));
174
Randy Abernethyd8187c52015-02-16 01:25:53 -0800175 client.testException('TException')
176 .then(function(response) {
Randy Abernethybd60b922015-02-26 16:59:14 -0800177 fail('testException: TException');
Randy Abernethyd8187c52015-02-16 01:25:53 -0800178 })
Randy Abernethybd60b922015-02-26 16:59:14 -0800179 .fail(function(err) {
180 assert.ok(err instanceof TException);
181 });
Randy Abernethyd8187c52015-02-16 01:25:53 -0800182
183 client.testException('Xception')
184 .then(function(response) {
Randy Abernethybd60b922015-02-26 16:59:14 -0800185 fail('testException: Xception');
Randy Abernethyd8187c52015-02-16 01:25:53 -0800186 })
187 .fail(function(err) {
Randy Abernethybd60b922015-02-26 16:59:14 -0800188 assert.ok(err instanceof ttypes.Xception);
Randy Abernethyd8187c52015-02-16 01:25:53 -0800189 assert.equal(err.errorCode, 1001);
190 assert.equal('Xception', err.message);
191 });
192
193 client.testException('no Exception')
194 .then(function(response) {
195 assert.equal(undefined, response); //void
196 })
197 .fail(fail('testException'));
198
199 client.testOneway(0, fail('testOneway: should not answer'));
200
201 checkOffByOne(function(done) {
202 client.testI32(-1)
203 .then(function(response) {
204 assert.equal(-1, response);
205 assert.end();
206 done();
207 })
208 .fail(fail('checkOffByOne'));
209 }, callback);
210 });
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800211};
212
213
214// Helper Functions
215// =========================================================
216
Randy Abernethyd8187c52015-02-16 01:25:53 -0800217function makeRecursiveCheck(assert) {
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800218
Randy Abernethyd8187c52015-02-16 01:25:53 -0800219 return function (map1, map2, msg) {
220 var equal = true;
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800221
Randy Abernethyd8187c52015-02-16 01:25:53 -0800222 var equal = checkRecursively(map1, map2);
223
224 assert.ok(equal, msg);
225
226 // deepEqual doesn't work with fields using node-int64
227 function checkRecursively(map1, map2) {
228 if (typeof map1 !== 'function' && typeof map2 !== 'function') {
229 if (!map1 || typeof map1 !== 'object') {
230 //Handle int64 types (which use node-int64 in Node.js JavaScript)
231 if ((typeof map1 === "number") && (typeof map2 === "object") &&
232 (map2.buffer) && (map2.buffer instanceof Buffer) && (map2.buffer.length === 8)) {
233 var n = new Int64(map2.buffer);
234 return map1 === n.toNumber();
235 } else {
236 return map1 == map2;
237 }
238 } else {
239 return Object.keys(map1).every(function(key) {
240 return checkRecursively(map1[key], map2[key]);
241 });
242 }
Randy Abernethy3b9ff4d2015-02-16 00:51:24 -0800243 }
244 }
245 }
246}
247
248function checkOffByOne(done, callback) {
249
250 var retry_limit = 30;
251 var retry_interval = 100;
252 var test_complete = false;
253 var retrys = 0;
254
255 /**
256 * redo a simple test after the oneway to make sure we aren't "off by one" --
257 * if the server treated oneway void like normal void, this next test will
258 * fail since it will get the void confirmation rather than the correct
259 * result. In this circumstance, the client will throw the exception:
260 *
261 * Because this is the last test against the server, when it completes
262 * the entire suite is complete by definition (the tests run serially).
263 */
264 done(function() {
265 test_complete = true;
266 });
267
268 //We wait up to retry_limit * retry_interval for the test suite to complete
269 function TestForCompletion() {
270 if(test_complete && callback) {
271 callback("Server successfully tested!");
272 } else {
273 if (++retrys < retry_limit) {
274 setTimeout(TestForCompletion, retry_interval);
275 } else if (callback) {
276 callback("Server test failed to complete after " +
277 (retry_limit * retry_interval / 1000) + " seconds");
278 }
279 }
280 }
281
282 setTimeout(TestForCompletion, retry_interval);
283}