blob: 604d5e5836dca3ded5b9c65b0c9e8e7180a15279 [file] [log] [blame]
wilfrem2c69b5a2015-04-20 19:24:50 +09001/*
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
Cameron Martincaef0ed2025-01-15 11:58:39 +010020// 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.
wilfrem2c69b5a2015-04-20 19:24:50 +090028
29import test = require("tape");
30import ttypes = require("./gen-nodejs/ThriftTest_types");
31import ThriftTest = require("./gen-nodejs/ThriftTest");
32import thrift = require("thrift");
33import Q = thrift.Q;
34import TException = thrift.Thrift.TException;
35var Int64 = require("node-int64");
36import testCases = require("./test-cases");
37
Cameron Martincaef0ed2025-01-15 11:58:39 +010038export function ThriftTestDriver(
39 client: ThriftTest.Client,
40 callback: (status: string) => void,
41) {
42 test("NodeJS Style Callback Client Tests", function (assert) {
wilfrem2c69b5a2015-04-20 19:24:50 +090043 var checkRecursively = makeRecursiveCheck(assert);
44
45 function makeAsserter(assertionFn: (a: any, b: any, msg?: string) => void) {
Cameron Martincaef0ed2025-01-15 11:58:39 +010046 return function (c: (string | any)[]) {
wilfrem2c69b5a2015-04-20 19:24:50 +090047 var fnName = c[0];
48 var expected = c[1];
Cameron Martincaef0ed2025-01-15 11:58:39 +010049 (<any>client)[fnName](expected, function (err: any, actual: any) {
wilfrem2c69b5a2015-04-20 19:24:50 +090050 assert.error(err, fnName + ": no callback error");
51 assertionFn(actual, expected, fnName);
Cameron Martincaef0ed2025-01-15 11:58:39 +010052 });
wilfrem2c69b5a2015-04-20 19:24:50 +090053 };
54 }
55
56 testCases.simple.forEach(makeAsserter(assert.equal));
Cameron Martincaef0ed2025-01-15 11:58:39 +010057 testCases.simpleLoose.forEach(
58 makeAsserter(function (a, e, m) {
59 assert.ok(a == e, m);
60 }),
61 );
wilfrem2c69b5a2015-04-20 19:24:50 +090062 testCases.deep.forEach(makeAsserter(assert.deepEqual));
63
Cameron Martincaef0ed2025-01-15 11:58:39 +010064 client.testMapMap(42, function (err, response) {
wilfrem2c69b5a2015-04-20 19:24:50 +090065 var expected: typeof response = {
Cameron Martincaef0ed2025-01-15 11:58:39 +010066 "4": { "1": 1, "2": 2, "3": 3, "4": 4 },
67 "-4": { "-4": -4, "-3": -3, "-2": -2, "-1": -1 },
wilfrem2c69b5a2015-04-20 19:24:50 +090068 };
Cameron Martincaef0ed2025-01-15 11:58:39 +010069 assert.error(err, "testMapMap: no callback error");
wilfrem2c69b5a2015-04-20 19:24:50 +090070 assert.deepEqual(expected, response, "testMapMap");
71 });
72
Cameron Martincaef0ed2025-01-15 11:58:39 +010073 client.testStruct(testCases.out, function (err, response) {
wilfrem2c69b5a2015-04-20 19:24:50 +090074 assert.error(err, "testStruct: no callback error");
75 checkRecursively(testCases.out, response, "testStruct");
76 });
77
Cameron Martincaef0ed2025-01-15 11:58:39 +010078 client.testNest(testCases.out2, function (err, response) {
wilfrem2c69b5a2015-04-20 19:24:50 +090079 assert.error(err, "testNest: no callback error");
80 checkRecursively(testCases.out2, response, "testNest");
81 });
82
Cameron Martincaef0ed2025-01-15 11:58:39 +010083 client.testInsanity(testCases.crazy, function (err, response) {
wilfrem2c69b5a2015-04-20 19:24:50 +090084 assert.error(err, "testInsanity: no callback error");
85 checkRecursively(testCases.insanity, response, "testInsanity");
86 });
87
Cameron Martincaef0ed2025-01-15 11:58:39 +010088 client.testException("TException", function (err, response) {
89 assert.ok(err instanceof TException, "testException: correct error type");
90 assert.ok(!Boolean(response), "testException: no response");
wilfrem2c69b5a2015-04-20 19:24:50 +090091 });
92
Cameron Martincaef0ed2025-01-15 11:58:39 +010093 client.testException("Xception", function (err, response) {
94 assert.ok(
95 err instanceof ttypes.Xception,
96 "testException: correct error type",
97 );
98 assert.ok(!Boolean(response), "testException: no response");
99 assert.equal(err.errorCode, 1001, "testException: correct error code");
100 assert.equal(
101 "Xception",
102 err.message,
103 "testException: correct error message",
104 );
wilfrem2c69b5a2015-04-20 19:24:50 +0900105 });
106
Cameron Martincaef0ed2025-01-15 11:58:39 +0100107 client.testException("no Exception", function (err, response) {
108 assert.error(err, "testException: no callback error");
109 assert.ok(!Boolean(response), "testException: no response");
wilfrem2c69b5a2015-04-20 19:24:50 +0900110 });
111
Cameron Martincaef0ed2025-01-15 11:58:39 +0100112 client.testOneway(0, function (err, response) {
113 assert.error(err, "testOneway: no callback error");
114 assert.strictEqual(response, undefined, "testOneway: void response");
wilfrem2c69b5a2015-04-20 19:24:50 +0900115 });
116
Cameron Martincaef0ed2025-01-15 11:58:39 +0100117 checkOffByOne(function (done) {
118 client.testI32(-1, function (err, response) {
wilfrem2c69b5a2015-04-20 19:24:50 +0900119 assert.error(err, "checkOffByOne: no callback error");
120 assert.equal(-1, response);
121 assert.end();
122 done();
123 });
124 }, callback);
wilfrem2c69b5a2015-04-20 19:24:50 +0900125 });
Cameron Martincaef0ed2025-01-15 11:58:39 +0100126}
wilfrem2c69b5a2015-04-20 19:24:50 +0900127
Cameron Martincaef0ed2025-01-15 11:58:39 +0100128export function ThriftTestDriverPromise(
129 client: ThriftTest.Client,
130 callback: (status: string) => void,
131) {
132 test("Q Promise Client Tests", function (assert) {
wilfrem2c69b5a2015-04-20 19:24:50 +0900133 var checkRecursively = makeRecursiveCheck(assert);
134
135 function fail(msg: string) {
Cameron Martincaef0ed2025-01-15 11:58:39 +0100136 return function (error, response) {
wilfrem2c69b5a2015-04-20 19:24:50 +0900137 if (error !== null) {
138 assert.fail(msg);
139 }
Cameron Martincaef0ed2025-01-15 11:58:39 +0100140 };
wilfrem2c69b5a2015-04-20 19:24:50 +0900141 }
142
143 function makeAsserter(assertionFn: (a: any, b: any, msg?: string) => void) {
Cameron Martincaef0ed2025-01-15 11:58:39 +0100144 return function (c: (string | any)[]) {
wilfrem2c69b5a2015-04-20 19:24:50 +0900145 var fnName = c[0];
146 var expected = c[1];
Cameron Martincaef0ed2025-01-15 11:58:39 +0100147 (<any>client)
148 [fnName](expected)
149 .then(function (actual: any) {
wilfrem2c69b5a2015-04-20 19:24:50 +0900150 assertionFn(actual, expected, fnName);
151 })
152 .fail(fail("fnName"));
153 };
154 }
155
156 testCases.simple.forEach(makeAsserter(assert.equal));
Cameron Martincaef0ed2025-01-15 11:58:39 +0100157 testCases.simpleLoose.forEach(
158 makeAsserter(function (a, e, m) {
159 assert.ok(a == e, m);
160 }),
161 );
wilfrem2c69b5a2015-04-20 19:24:50 +0900162 testCases.deep.forEach(makeAsserter(assert.deepEqual));
163
164 Q.resolve(client.testStruct(testCases.out))
Cameron Martincaef0ed2025-01-15 11:58:39 +0100165 .then(function (response) {
wilfrem2c69b5a2015-04-20 19:24:50 +0900166 checkRecursively(testCases.out, response, "testStruct");
167 })
168 .fail(fail("testStruct"));
169
170 Q.resolve(client.testNest(testCases.out2))
Cameron Martincaef0ed2025-01-15 11:58:39 +0100171 .then(function (response) {
wilfrem2c69b5a2015-04-20 19:24:50 +0900172 checkRecursively(testCases.out2, response, "testNest");
173 })
174 .fail(fail("testNest"));
175
176 Q.resolve(client.testInsanity(testCases.crazy))
Cameron Martincaef0ed2025-01-15 11:58:39 +0100177 .then(function (response) {
wilfrem2c69b5a2015-04-20 19:24:50 +0900178 checkRecursively(testCases.insanity, response, "testInsanity");
179 })
180 .fail(fail("testInsanity"));
181
182 Q.resolve(client.testException("TException"))
Cameron Martincaef0ed2025-01-15 11:58:39 +0100183 .then(function (response) {
wilfrem2c69b5a2015-04-20 19:24:50 +0900184 fail("testException: TException");
185 })
Cameron Martincaef0ed2025-01-15 11:58:39 +0100186 .fail(function (err) {
wilfrem2c69b5a2015-04-20 19:24:50 +0900187 assert.ok(err instanceof TException);
188 });
189
190 Q.resolve(client.testException("Xception"))
Cameron Martincaef0ed2025-01-15 11:58:39 +0100191 .then(function (response) {
wilfrem2c69b5a2015-04-20 19:24:50 +0900192 fail("testException: Xception");
193 })
Cameron Martincaef0ed2025-01-15 11:58:39 +0100194 .fail(function (err) {
wilfrem2c69b5a2015-04-20 19:24:50 +0900195 assert.ok(err instanceof ttypes.Xception);
196 assert.equal(err.errorCode, 1001);
197 assert.equal("Xception", err.message);
198 });
199
200 Q.resolve(client.testException("no Exception"))
Cameron Martincaef0ed2025-01-15 11:58:39 +0100201 .then(function (response) {
wilfrem2c69b5a2015-04-20 19:24:50 +0900202 assert.equal(undefined, response); //void
203 })
204 .fail(fail("testException"));
205
206 client.testOneway(0, fail("testOneway: should not answer"));
207
Cameron Martincaef0ed2025-01-15 11:58:39 +0100208 checkOffByOne(function (done) {
wilfrem2c69b5a2015-04-20 19:24:50 +0900209 Q.resolve(client.testI32(-1))
Cameron Martincaef0ed2025-01-15 11:58:39 +0100210 .then(function (response) {
211 assert.equal(-1, response);
212 assert.end();
213 done();
wilfrem2c69b5a2015-04-20 19:24:50 +0900214 })
215 .fail(fail("checkOffByOne"));
216 }, callback);
217 });
Cameron Martincaef0ed2025-01-15 11:58:39 +0100218}
wilfrem2c69b5a2015-04-20 19:24:50 +0900219
220// Helper Functions
221// =========================================================
222
223function makeRecursiveCheck(assert: test.Test) {
wilfrem2c69b5a2015-04-20 19:24:50 +0900224 return function (map1: any, map2: any, msg: string) {
225 var equal = true;
226
227 var equal = checkRecursively(map1, map2);
228
229 assert.ok(equal, msg);
230
231 // deepEqual doesn't work with fields using node-int64
Cameron Martincaef0ed2025-01-15 11:58:39 +0100232 function checkRecursively(map1: any, map2: any): boolean {
wilfrem2c69b5a2015-04-20 19:24:50 +0900233 if (!(typeof map1 !== "function" && typeof map2 !== "function")) {
234 return false;
235 }
236 if (!map1 || typeof map1 !== "object") {
237 //Handle int64 types (which use node-int64 in Node.js JavaScript)
Cameron Martincaef0ed2025-01-15 11:58:39 +0100238 if (
239 typeof map1 === "number" &&
240 typeof map2 === "object" &&
241 map2.buffer &&
242 map2.buffer instanceof Buffer &&
243 map2.buffer.length === 8
244 ) {
wilfrem2c69b5a2015-04-20 19:24:50 +0900245 var n = new Int64(map2.buffer);
246 return map1 === n.toNumber();
247 } else {
248 return map1 == map2;
249 }
250 } else {
Cameron Martincaef0ed2025-01-15 11:58:39 +0100251 return Object.keys(map1).every(function (key) {
wilfrem2c69b5a2015-04-20 19:24:50 +0900252 return checkRecursively(map1[key], map2[key]);
253 });
254 }
255 }
Cameron Martincaef0ed2025-01-15 11:58:39 +0100256 };
wilfrem2c69b5a2015-04-20 19:24:50 +0900257}
258
Cameron Martincaef0ed2025-01-15 11:58:39 +0100259function checkOffByOne(
260 done: (callback: () => void) => void,
261 callback: (message: string) => void,
262) {
wilfrem2c69b5a2015-04-20 19:24:50 +0900263 var retry_limit = 30;
264 var retry_interval = 100;
265 var test_complete = false;
266 var retrys = 0;
267
268 /**
269 * redo a simple test after the oneway to make sure we aren't "off by one" --
270 * if the server treated oneway void like normal void, this next test will
271 * fail since it will get the void confirmation rather than the correct
272 * result. In this circumstance, the client will throw the exception:
273 *
274 * Because this is the last test against the server, when it completes
275 * the entire suite is complete by definition (the tests run serially).
276 */
Cameron Martincaef0ed2025-01-15 11:58:39 +0100277 done(function () {
wilfrem2c69b5a2015-04-20 19:24:50 +0900278 test_complete = true;
279 });
280
281 //We wait up to retry_limit * retry_interval for the test suite to complete
282 function TestForCompletion() {
Cameron Martincaef0ed2025-01-15 11:58:39 +0100283 if (test_complete && callback) {
wilfrem2c69b5a2015-04-20 19:24:50 +0900284 callback("Server successfully tested!");
285 } else {
286 if (++retrys < retry_limit) {
287 setTimeout(TestForCompletion, retry_interval);
288 } else if (callback) {
Cameron Martincaef0ed2025-01-15 11:58:39 +0100289 callback(
290 "Server test failed to complete after " +
291 (retry_limit * retry_interval) / 1000 +
292 " seconds",
293 );
wilfrem2c69b5a2015-04-20 19:24:50 +0900294 }
295 }
296 }
297
298 setTimeout(TestForCompletion, retry_interval);
299}