diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/jaegertracing/thrift/lib/nodejs/test | |
parent | Initial commit. (diff) | |
download | ceph-upstream.tar.xz ceph-upstream.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/jaegertracing/thrift/lib/nodejs/test')
19 files changed, 2310 insertions, 0 deletions
diff --git a/src/jaegertracing/thrift/lib/nodejs/test/binary.test.js b/src/jaegertracing/thrift/lib/nodejs/test/binary.test.js new file mode 100644 index 000000000..187cd1874 --- /dev/null +++ b/src/jaegertracing/thrift/lib/nodejs/test/binary.test.js @@ -0,0 +1,214 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const test = require("tape"); +const binary = require("thrift/binary"); + +const cases = { + "Should read signed byte": function(assert) { + assert.equal(1, binary.readByte(0x01)); + assert.equal(-1, binary.readByte(0xff)); + + assert.equal(127, binary.readByte(0x7f)); + assert.equal(-128, binary.readByte(0x80)); + assert.end(); + }, + "Should write byte": function(assert) { + //Protocol simply writes to the buffer. Nothing to test.. yet. + assert.ok(true); + assert.end(); + }, + "Should read I16": function(assert) { + assert.equal(0, binary.readI16([0x00, 0x00])); + assert.equal(1, binary.readI16([0x00, 0x01])); + assert.equal(-1, binary.readI16([0xff, 0xff])); + + // Min I16 + assert.equal(-32768, binary.readI16([0x80, 0x00])); + // Max I16 + assert.equal(32767, binary.readI16([0x7f, 0xff])); + assert.end(); + }, + + "Should write I16": function(assert) { + assert.deepEqual([0x00, 0x00], binary.writeI16([], 0)); + assert.deepEqual([0x00, 0x01], binary.writeI16([], 1)); + assert.deepEqual([0xff, 0xff], binary.writeI16([], -1)); + + // Min I16 + assert.deepEqual([0x80, 0x00], binary.writeI16([], -32768)); + // Max I16 + assert.deepEqual([0x7f, 0xff], binary.writeI16([], 32767)); + assert.end(); + }, + + "Should read I32": function(assert) { + assert.equal(0, binary.readI32([0x00, 0x00, 0x00, 0x00])); + assert.equal(1, binary.readI32([0x00, 0x00, 0x00, 0x01])); + assert.equal(-1, binary.readI32([0xff, 0xff, 0xff, 0xff])); + + // Min I32 + assert.equal(-2147483648, binary.readI32([0x80, 0x00, 0x00, 0x00])); + // Max I32 + assert.equal(2147483647, binary.readI32([0x7f, 0xff, 0xff, 0xff])); + assert.end(); + }, + + "Should write I32": function(assert) { + assert.deepEqual([0x00, 0x00, 0x00, 0x00], binary.writeI32([], 0)); + assert.deepEqual([0x00, 0x00, 0x00, 0x01], binary.writeI32([], 1)); + assert.deepEqual([0xff, 0xff, 0xff, 0xff], binary.writeI32([], -1)); + + // Min I32 + assert.deepEqual( + [0x80, 0x00, 0x00, 0x00], + binary.writeI32([], -2147483648) + ); + // Max I32 + assert.deepEqual([0x7f, 0xff, 0xff, 0xff], binary.writeI32([], 2147483647)); + assert.end(); + }, + + "Should read doubles": function(assert) { + assert.equal( + 0, + binary.readDouble([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) + ); + assert.equal( + 0, + binary.readDouble([0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) + ); + assert.equal( + 1, + binary.readDouble([0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) + ); + assert.equal( + 2, + binary.readDouble([0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) + ); + assert.equal( + -2, + binary.readDouble([0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) + ); + + assert.equal( + Math.PI, + binary.readDouble([0x40, 0x9, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18]) + ); + + assert.equal( + Infinity, + binary.readDouble([0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) + ); + assert.equal( + -Infinity, + binary.readDouble([0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) + ); + + assert.ok( + isNaN(binary.readDouble([0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])) + ); + + assert.equal( + 1 / 3, + binary.readDouble([0x3f, 0xd5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55]) + ); + + // Min subnormal positive double + assert.equal( + 4.9406564584124654e-324, + binary.readDouble([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]) + ); + // Min normal positive double + assert.equal( + 2.2250738585072014e-308, + binary.readDouble([0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) + ); + // Max positive double + assert.equal( + 1.7976931348623157e308, + binary.readDouble([0x7f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]) + ); + assert.end(); + }, + + "Should write doubles": function(assert) { + assert.deepEqual( + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], + binary.writeDouble([], 0) + ); + assert.deepEqual( + [0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], + binary.writeDouble([], 1) + ); + assert.deepEqual( + [0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], + binary.writeDouble([], 2) + ); + assert.deepEqual( + [0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], + binary.writeDouble([], -2) + ); + + assert.deepEqual( + [0x40, 0x9, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18], + binary.writeDouble([], Math.PI) + ); + + assert.deepEqual( + [0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], + binary.writeDouble([], Infinity) + ); + assert.deepEqual( + [0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], + binary.writeDouble([], -Infinity) + ); + + assert.deepEqual( + [0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], + binary.writeDouble([], NaN) + ); + + assert.deepEqual( + [0x3f, 0xd5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55], + binary.writeDouble([], 1 / 3) + ); + + // Min subnormal positive double + assert.deepEqual( + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01], + binary.writeDouble([], 4.9406564584124654e-324) + ); + // Min normal positive double + assert.deepEqual( + [0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], + binary.writeDouble([], 2.2250738585072014e-308) + ); + // Max positive double + assert.deepEqual( + [0x7f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], + binary.writeDouble([], 1.7976931348623157e308) + ); + assert.end(); + } +}; + +Object.keys(cases).forEach(function(caseName) { + test(caseName, cases[caseName]); +}); diff --git a/src/jaegertracing/thrift/lib/nodejs/test/certificates.README b/src/jaegertracing/thrift/lib/nodejs/test/certificates.README new file mode 100644 index 000000000..06c507e7d --- /dev/null +++ b/src/jaegertracing/thrift/lib/nodejs/test/certificates.README @@ -0,0 +1,7 @@ +server.crt AND server.key ARE PROVIDED FOR TEST PURPOSE AND SHOULD *NEVER* BE USED IN PRODUCTION + + +Origin of the test key and cert is the folder test/keys of Apache Thrift source code distribution + +We need copies for npm deployment + diff --git a/src/jaegertracing/thrift/lib/nodejs/test/client.js b/src/jaegertracing/thrift/lib/nodejs/test/client.js new file mode 100644 index 000000000..49e3a5ec9 --- /dev/null +++ b/src/jaegertracing/thrift/lib/nodejs/test/client.js @@ -0,0 +1,170 @@ +#!/usr/bin/env node + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const assert = require("assert"); +const thrift = require("thrift"); +const helpers = require("./helpers"); + +const ThriftTest = require(`./${helpers.genPath}/ThriftTest`); +const ThriftTestDriver = require("./test_driver").ThriftTestDriver; +const ThriftTestDriverPromise = require("./test_driver") + .ThriftTestDriverPromise; +const SecondService = require(`./${helpers.genPath}/SecondService`); + +const program = require("commander"); + +program + .option( + "-p, --protocol <protocol>", + "Set thrift protocol (binary|compact|json) [protocol]" + ) + .option( + "-t, --transport <transport>", + "Set thrift transport (buffered|framed|http) [transport]" + ) + .option("--port <port>", "Set thrift server port number to connect", 9090) + .option("--host <host>", "Set thrift server host to connect", "localhost") + .option( + "--domain-socket <path>", + "Set thrift server unix domain socket to connect" + ) + .option("--ssl", "use SSL transport") + .option("--callback", "test with callback style functions") + .option( + "-t, --type <type>", + "Select server type (http|multiplex|tcp|websocket)", + "tcp" + ) + .option("--es6", "Use es6 code") + .option("--es5", "Use es5 code") + .parse(process.argv); + +const host = program.host; +const port = program.port; +const domainSocket = program.domainSocket; +const ssl = program.ssl; +let type = program.type; + +/* for compatibility with cross test invocation for http transport testing */ +if (program.transport === "http") { + program.transport = "buffered"; + type = "http"; +} + +const options = { + transport: helpers.transports[program.transport], + protocol: helpers.protocols[program.protocol] +}; + +if (type === "http" || type === "websocket") { + options.path = "/test"; +} + +if (type === "http") { + options.headers = { Connection: "close" }; +} + +if (ssl) { + if (type === "tcp" || type === "multiplex") { + options.rejectUnauthorized = false; + } else if (type === "http") { + options.nodeOptions = { rejectUnauthorized: false }; + options.https = true; + } else if (type === "websocket") { + options.wsOptions = { rejectUnauthorized: false }; + options.secure = true; + } +} + +let connection; +let client; +const testDriver = program.callback + ? ThriftTestDriver + : ThriftTestDriverPromise; +if (helpers.ecmaMode === "es6" && program.callback) { + console.log("ES6 does not support callback style"); + process.exit(0); +} + +if (type === "tcp" || type === "multiplex") { + if (domainSocket) { + connection = thrift.createUDSConnection(domainSocket, options); + } else { + connection = ssl + ? thrift.createSSLConnection(host, port, options) + : thrift.createConnection(host, port, options); + } +} else if (type === "http") { + if (domainSocket) { + connection = thrift.createHttpUDSConnection(domainSocket, options); + } else { + connection = thrift.createHttpConnection(host, port, options); + } +} else if (type === "websocket") { + connection = thrift.createWSConnection(host, port, options); + connection.open(); +} + +connection.on("error", function(err) { + assert(false, err); +}); + +if (type === "tcp") { + client = thrift.createClient(ThriftTest, connection); + runTests(); +} else if (type === "multiplex") { + const mp = new thrift.Multiplexer(); + client = mp.createClient("ThriftTest", ThriftTest, connection); + const secondclient = mp.createClient( + "SecondService", + SecondService, + connection + ); + + connection.on("connect", function() { + secondclient.secondtestString("Test", function(err, response) { + assert(!err); + assert.equal('testString("Test")', response); + }); + + runTests(); + }); +} else if (type === "http") { + client = thrift.createHttpClient(ThriftTest, connection); + runTests(); +} else if (type === "websocket") { + client = thrift.createWSClient(ThriftTest, connection); + runTests(); +} + +function runTests() { + testDriver(client, function(status) { + console.log(status); + if (type !== "http" && type !== "websocket") { + connection.end(); + } + if (type !== "multiplex") { + process.exit(0); + } + }); +} + +exports.expressoTest = function() {}; diff --git a/src/jaegertracing/thrift/lib/nodejs/test/deep-constructor.test.js b/src/jaegertracing/thrift/lib/nodejs/test/deep-constructor.test.js new file mode 100644 index 000000000..504dacf0b --- /dev/null +++ b/src/jaegertracing/thrift/lib/nodejs/test/deep-constructor.test.js @@ -0,0 +1,333 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const ttypes = require("./gen-nodejs/JsDeepConstructorTest_types"); +const thrift = require("thrift"); +const test = require("tape"); +const bufferEquals = require("buffer-equals"); + +function serializeBinary(data) { + let buff; + const transport = new thrift.TBufferedTransport(null, function(msg) { + buff = msg; + }); + const prot = new thrift.TBinaryProtocol(transport); + data.write(prot); + prot.flush(); + return buff; +} + +function deserializeBinary(serialized, type) { + const t = new thrift.TFramedTransport(serialized); + const p = new thrift.TBinaryProtocol(t); + const data = new type(); + data.read(p); + return data; +} + +function serializeJSON(data) { + let buff; + const transport = new thrift.TBufferedTransport(null, function(msg) { + buff = msg; + }); + const protocol = new thrift.TJSONProtocol(transport); + protocol.writeMessageBegin("", 0, 0); + data.write(protocol); + protocol.writeMessageEnd(); + protocol.flush(); + return buff; +} + +function deserializeJSON(serialized, type) { + const transport = new thrift.TFramedTransport(serialized); + const protocol = new thrift.TJSONProtocol(transport); + protocol.readMessageBegin(); + const data = new type(); + data.read(protocol); + protocol.readMessageEnd(); + return data; +} + +function createThriftObj() { + return new ttypes.Complex({ + struct_field: new ttypes.Simple({ value: "a" }), + + struct_list_field: [ + new ttypes.Simple({ value: "b" }), + new ttypes.Simple({ value: "c" }) + ], + + struct_set_field: [ + new ttypes.Simple({ value: "d" }), + new ttypes.Simple({ value: "e" }) + ], + + struct_map_field: { + A: new ttypes.Simple({ value: "f" }), + B: new ttypes.Simple({ value: "g" }) + }, + + struct_nested_containers_field: [ + [ + { + C: [ + new ttypes.Simple({ value: "h" }), + new ttypes.Simple({ value: "i" }) + ] + } + ] + ], + + struct_nested_containers_field2: { + D: [ + { + DA: new ttypes.Simple({ value: "j" }) + }, + { + DB: new ttypes.Simple({ value: "k" }) + } + ] + }, + + list_of_list_field: [ + ["l00", "l01", "l02"], + ["l10", "l11", "l12"], + ["l20", "l21", "l22"] + ], + + list_of_list_of_list_field: [ + [ + ["m000", "m001", "m002"], + ["m010", "m011", "m012"], + ["m020", "m021", "m022"] + ], + [ + ["m100", "m101", "m102"], + ["m110", "m111", "m112"], + ["m120", "m121", "m122"] + ], + [ + ["m200", "m201", "m202"], + ["m210", "m211", "m212"], + ["m220", "m221", "m222"] + ] + ] + }); +} + +function createJsObj() { + return { + struct_field: { value: "a" }, + + struct_list_field: [{ value: "b" }, { value: "c" }], + + struct_set_field: [{ value: "d" }, { value: "e" }], + + struct_map_field: { + A: { value: "f" }, + B: { value: "g" } + }, + + struct_nested_containers_field: [ + [ + { + C: [{ value: "h" }, { value: "i" }] + } + ] + ], + + struct_nested_containers_field2: { + D: [ + { + DA: { value: "j" } + }, + { + DB: { value: "k" } + } + ] + }, + + list_of_list_field: [ + ["l00", "l01", "l02"], + ["l10", "l11", "l12"], + ["l20", "l21", "l22"] + ], + + list_of_list_of_list_field: [ + [ + ["m000", "m001", "m002"], + ["m010", "m011", "m012"], + ["m020", "m021", "m022"] + ], + [ + ["m100", "m101", "m102"], + ["m110", "m111", "m112"], + ["m120", "m121", "m122"] + ], + [ + ["m200", "m201", "m202"], + ["m210", "m211", "m212"], + ["m220", "m221", "m222"] + ] + ] + }; +} + +function assertValues(obj, assert) { + assert.equals(obj.struct_field.value, "a"); + assert.equals(obj.struct_list_field[0].value, "b"); + assert.equals(obj.struct_list_field[1].value, "c"); + assert.equals(obj.struct_set_field[0].value, "d"); + assert.equals(obj.struct_set_field[1].value, "e"); + assert.equals(obj.struct_map_field.A.value, "f"); + assert.equals(obj.struct_map_field.B.value, "g"); + assert.equals(obj.struct_nested_containers_field[0][0].C[0].value, "h"); + assert.equals(obj.struct_nested_containers_field[0][0].C[1].value, "i"); + assert.equals(obj.struct_nested_containers_field2.D[0].DA.value, "j"); + assert.equals(obj.struct_nested_containers_field2.D[1].DB.value, "k"); + assert.equals(obj.list_of_list_field[0][0], "l00"); + assert.equals(obj.list_of_list_field[0][1], "l01"); + assert.equals(obj.list_of_list_field[0][2], "l02"); + assert.equals(obj.list_of_list_field[1][0], "l10"); + assert.equals(obj.list_of_list_field[1][1], "l11"); + assert.equals(obj.list_of_list_field[1][2], "l12"); + assert.equals(obj.list_of_list_field[2][0], "l20"); + assert.equals(obj.list_of_list_field[2][1], "l21"); + assert.equals(obj.list_of_list_field[2][2], "l22"); + + assert.equals(obj.list_of_list_of_list_field[0][0][0], "m000"); + assert.equals(obj.list_of_list_of_list_field[0][0][1], "m001"); + assert.equals(obj.list_of_list_of_list_field[0][0][2], "m002"); + assert.equals(obj.list_of_list_of_list_field[0][1][0], "m010"); + assert.equals(obj.list_of_list_of_list_field[0][1][1], "m011"); + assert.equals(obj.list_of_list_of_list_field[0][1][2], "m012"); + assert.equals(obj.list_of_list_of_list_field[0][2][0], "m020"); + assert.equals(obj.list_of_list_of_list_field[0][2][1], "m021"); + assert.equals(obj.list_of_list_of_list_field[0][2][2], "m022"); + + assert.equals(obj.list_of_list_of_list_field[1][0][0], "m100"); + assert.equals(obj.list_of_list_of_list_field[1][0][1], "m101"); + assert.equals(obj.list_of_list_of_list_field[1][0][2], "m102"); + assert.equals(obj.list_of_list_of_list_field[1][1][0], "m110"); + assert.equals(obj.list_of_list_of_list_field[1][1][1], "m111"); + assert.equals(obj.list_of_list_of_list_field[1][1][2], "m112"); + assert.equals(obj.list_of_list_of_list_field[1][2][0], "m120"); + assert.equals(obj.list_of_list_of_list_field[1][2][1], "m121"); + assert.equals(obj.list_of_list_of_list_field[1][2][2], "m122"); + + assert.equals(obj.list_of_list_of_list_field[2][0][0], "m200"); + assert.equals(obj.list_of_list_of_list_field[2][0][1], "m201"); + assert.equals(obj.list_of_list_of_list_field[2][0][2], "m202"); + assert.equals(obj.list_of_list_of_list_field[2][1][0], "m210"); + assert.equals(obj.list_of_list_of_list_field[2][1][1], "m211"); + assert.equals(obj.list_of_list_of_list_field[2][1][2], "m212"); + assert.equals(obj.list_of_list_of_list_field[2][2][0], "m220"); + assert.equals(obj.list_of_list_of_list_field[2][2][1], "m221"); + assert.equals(obj.list_of_list_of_list_field[2][2][2], "m222"); +} + +function createTestCases(serialize, deserialize) { + const cases = { + "Serialize/deserialize should return equal object": function(assert) { + const tObj = createThriftObj(); + const received = deserialize(serialize(tObj), ttypes.Complex); + assert.ok(tObj !== received, "not the same object"); + assert.deepEqual(tObj, received); + assert.end(); + }, + + "Nested structs and containers initialized from plain js objects should serialize same as if initialized from thrift objects": function( + assert + ) { + const tObj1 = createThriftObj(); + const tObj2 = new ttypes.Complex(createJsObj()); + assertValues(tObj2, assert); + const s1 = serialize(tObj1); + const s2 = serialize(tObj2); + assert.ok(bufferEquals(s1, s2)); + assert.end(); + }, + + "Modifications to args object should not affect constructed Thrift object": function( + assert + ) { + const args = createJsObj(); + assertValues(args, assert); + + const tObj = new ttypes.Complex(args); + assertValues(tObj, assert); + + args.struct_field.value = "ZZZ"; + args.struct_list_field[0].value = "ZZZ"; + args.struct_list_field[1].value = "ZZZ"; + args.struct_set_field[0].value = "ZZZ"; + args.struct_set_field[1].value = "ZZZ"; + args.struct_map_field.A.value = "ZZZ"; + args.struct_map_field.B.value = "ZZZ"; + args.struct_nested_containers_field[0][0].C[0] = "ZZZ"; + args.struct_nested_containers_field[0][0].C[1] = "ZZZ"; + args.struct_nested_containers_field2.D[0].DA = "ZZZ"; + args.struct_nested_containers_field2.D[0].DB = "ZZZ"; + + assertValues(tObj, assert); + assert.end(); + }, + + "nulls are ok": function(assert) { + const tObj = new ttypes.Complex({ + struct_field: null, + struct_list_field: null, + struct_set_field: null, + struct_map_field: null, + struct_nested_containers_field: null, + struct_nested_containers_field2: null + }); + const received = deserialize(serialize(tObj), ttypes.Complex); + assert.strictEqual(tObj.struct_field, null); + assert.ok(tObj !== received); + assert.deepEqual(tObj, received); + assert.end(); + }, + + "Can make list with objects": function(assert) { + const tObj = new ttypes.ComplexList({ + struct_list_field: [new ttypes.Complex({})] + }); + const innerObj = tObj.struct_list_field[0]; + assert.ok(innerObj instanceof ttypes.Complex); + assert.strictEqual(innerObj.struct_field, null); + assert.strictEqual(innerObj.struct_list_field, null); + assert.strictEqual(innerObj.struct_set_field, null); + assert.strictEqual(innerObj.struct_map_field, null); + assert.strictEqual(innerObj.struct_nested_containers_field, null); + assert.strictEqual(innerObj.struct_nested_containers_field2, null); + assert.end(); + } + }; + return cases; +} + +function run(name, cases) { + Object.keys(cases).forEach(function(caseName) { + test(name + ": " + caseName, cases[caseName]); + }); +} + +run("binary", createTestCases(serializeBinary, deserializeBinary)); +run("json", createTestCases(serializeJSON, deserializeJSON)); diff --git a/src/jaegertracing/thrift/lib/nodejs/test/episodic-code-generation-test/client.js b/src/jaegertracing/thrift/lib/nodejs/test/episodic-code-generation-test/client.js new file mode 100644 index 000000000..55dc70269 --- /dev/null +++ b/src/jaegertracing/thrift/lib/nodejs/test/episodic-code-generation-test/client.js @@ -0,0 +1,77 @@ +#!/usr/bin/env node + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const assert = require("assert"); +const test = require("tape"); +const thrift = require("thrift"); +const program = require("commander"); + +program + .option("--host <host>", "Set the thrift server host to connect", "localhost") + .option("--port <port>", "Set the thrift server port number to connect", 9090) + .parse(process.argv); + +const Service = require("./gen-2/second-episode/gen-nodejs/Service"); +const Types = require("types-package/first-episode/Types_types"); + +const host = program.host; +const port = program.port; + +const options = { + transport: thrift.TBufferedTransport, + protocol: thrift.TJSONProtocol +}; + +const connection = thrift.createConnection(host, port, options); +const testDriver = function(client, callback) { + test("NodeJS episodic compilation client-server test", function(assert) { + const type1Object = new Types.Type1(); + type1Object.number = 42; + type1Object.message = "The answer"; + client.testEpisode(type1Object, function(err, response) { + assert.error(err, "no callback error"); + assert.equal(response.number, type1Object.number + 1); + assert.equal( + response.message, + type1Object.message + " [Hello from the server]" + ); + assert.end(); + callback("Server successfully tested"); + }); + }); +}; + +connection.on("error", function(err) { + assert(false, err); +}); + +const client = thrift.createClient(Service, connection); + +runTests(); + +function runTests() { + testDriver(client, function(status) { + console.log(status); + connection.destroy(); + }); +} + +exports.expressoTest = function() {}; diff --git a/src/jaegertracing/thrift/lib/nodejs/test/episodic-code-generation-test/episodic_compilation.package.json b/src/jaegertracing/thrift/lib/nodejs/test/episodic-code-generation-test/episodic_compilation.package.json new file mode 100644 index 000000000..7a78b4beb --- /dev/null +++ b/src/jaegertracing/thrift/lib/nodejs/test/episodic-code-generation-test/episodic_compilation.package.json @@ -0,0 +1,3 @@ +{ + "name": "types-package" +} diff --git a/src/jaegertracing/thrift/lib/nodejs/test/episodic-code-generation-test/server.js b/src/jaegertracing/thrift/lib/nodejs/test/episodic-code-generation-test/server.js new file mode 100644 index 000000000..2917b681c --- /dev/null +++ b/src/jaegertracing/thrift/lib/nodejs/test/episodic-code-generation-test/server.js @@ -0,0 +1,50 @@ +#!/usr/bin/env node + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * 'License'); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const thrift = require("../../lib/thrift"); +const program = require("commander"); + +program + .option("--port <port>", "Set the thrift server port", 9090) + .parse(process.argv); + +const Service = require("./gen-2/second-episode/gen-nodejs/Service"); +const Types = require("types-package/first-episode/Types_types"); + +const port = program.port; + +const options = { + transport: thrift.TBufferedTransport, + protocol: thrift.TJSONProtocol +}; + +const ServiceHandler = { + testEpisode: function(receivedType1Object) { + const type1Object = new Types.Type1(); + type1Object.number = receivedType1Object.number + 1; + type1Object.message = + receivedType1Object.message + " [Hello from the server]"; + return type1Object; + } +}; + +const server = thrift.createServer(Service, ServiceHandler, options); +server.listen(port); diff --git a/src/jaegertracing/thrift/lib/nodejs/test/exceptions.js b/src/jaegertracing/thrift/lib/nodejs/test/exceptions.js new file mode 100644 index 000000000..ab2798a26 --- /dev/null +++ b/src/jaegertracing/thrift/lib/nodejs/test/exceptions.js @@ -0,0 +1,146 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +"use strict"; +const test = require("tape"); +const thrift = require("../lib/thrift/thrift.js"); +const InputBufferUnderrunError = require("../lib/thrift/input_buffer_underrun_error"); + +test("TApplicationException", function t(assert) { + const e = new thrift.TApplicationException(1, "foo"); + assert.ok( + e instanceof thrift.TApplicationException, + "is instanceof TApplicationException" + ); + assert.ok(e instanceof thrift.TException, "is instanceof TException"); + assert.ok(e instanceof Error, "is instanceof Error"); + assert.equal(typeof e.stack, "string", "has stack trace"); + assert.ok( + /^TApplicationException: foo/.test(e.stack), + "Stack trace has correct error name and message" + ); + assert.ok( + e.stack.indexOf("test/exceptions.js:7:11") !== -1, + "stack trace starts on correct line and column" + ); + assert.equal( + e.name, + "TApplicationException", + "has function name TApplicationException" + ); + assert.equal(e.message, "foo", 'has error message "foo"'); + assert.equal(e.type, 1, "has type 1"); + assert.end(); +}); + +test("unexpected TApplicationException ", function t(assert) { + const e = new thrift.TApplicationException(1, 100); + assert.ok( + e instanceof thrift.TApplicationException, + "is instanceof TApplicationException" + ); + assert.ok(e instanceof thrift.TException, "is instanceof TException"); + assert.ok(e instanceof Error, "is instanceof Error"); + assert.equal(typeof e.stack, "string", "has stack trace"); + assert.ok( + /^TApplicationException: 100/.test(e.stack), + "Stack trace has correct error name and message" + ); + assert.ok( + e.stack.indexOf("test/exceptions.js:7:11") !== -1, + "stack trace starts on correct line and column" + ); + assert.equal( + e.name, + "TApplicationException", + "has function name TApplicationException" + ); + assert.equal(e.message, 100, "has error message 100"); + assert.equal(e.type, 1, "has type 1"); + assert.end(); +}); + +test("TException", function t(assert) { + const e = new thrift.TException("foo"); + assert.ok(e instanceof thrift.TException, "is instanceof TException"); + assert.ok(e instanceof Error, "is instanceof Error"); + assert.equal(typeof e.stack, "string", "has stack trace"); + assert.ok( + /^TException: foo/.test(e.stack), + "Stack trace has correct error name and message" + ); + assert.ok( + e.stack.indexOf("test/exceptions.js:21:11") !== -1, + "stack trace starts on correct line and column" + ); + assert.equal(e.name, "TException", "has function name TException"); + assert.equal(e.message, "foo", 'has error message "foo"'); + assert.end(); +}); + +test("TProtocolException", function t(assert) { + const e = new thrift.TProtocolException(1, "foo"); + assert.ok( + e instanceof thrift.TProtocolException, + "is instanceof TProtocolException" + ); + assert.ok(e instanceof Error, "is instanceof Error"); + assert.equal(typeof e.stack, "string", "has stack trace"); + assert.ok( + /^TProtocolException: foo/.test(e.stack), + "Stack trace has correct error name and message" + ); + assert.ok( + e.stack.indexOf("test/exceptions.js:33:11") !== -1, + "stack trace starts on correct line and column" + ); + assert.equal( + e.name, + "TProtocolException", + "has function name TProtocolException" + ); + assert.equal(e.message, "foo", 'has error message "foo"'); + assert.equal(e.type, 1, "has type 1"); + assert.end(); +}); + +test("InputBufferUnderrunError", function t(assert) { + const e = new InputBufferUnderrunError("foo"); + assert.ok( + e instanceof InputBufferUnderrunError, + "is instanceof InputBufferUnderrunError" + ); + assert.ok(e instanceof Error, "is instanceof Error"); + assert.equal(typeof e.stack, "string", "has stack trace"); + assert.ok( + /^InputBufferUnderrunError: foo/.test(e.stack), + "Stack trace has correct error name and message" + ); + assert.ok( + e.stack.indexOf("test/exceptions.js:46:11") !== -1, + "stack trace starts on correct line and column" + ); + assert.equal( + e.name, + "InputBufferUnderrunError", + "has function name InputBufferUnderrunError" + ); + assert.equal(e.message, "foo", 'has error message "foo"'); + assert.end(); +}); diff --git a/src/jaegertracing/thrift/lib/nodejs/test/header.test.js b/src/jaegertracing/thrift/lib/nodejs/test/header.test.js new file mode 100644 index 000000000..efd7f81d5 --- /dev/null +++ b/src/jaegertracing/thrift/lib/nodejs/test/header.test.js @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const TFramedTransport = require("../lib/thrift/framed_transport"); +const THeaderTransport = require("../lib/thrift/header_transport"); +const THeaderProtocol = require("../lib/thrift/header_protocol"); +const thrift = require("../lib/thrift"); +const fs = require("fs"); +const test = require("tape"); +const path = require("path"); + +const headerPayload = fs.readFileSync( + path.join(__dirname, "test_header_payload") +); + +const cases = { + "Should read headers from payload": function(assert) { + const transport = new TFramedTransport(); + transport.inBuf = Buffer.from(headerPayload); + + const headers = transport.readHeaders(); + assert.equals(headers.Parent, "shoobar"); + assert.equals(headers.Trace, "abcde"); + assert.end(); + }, + "Should read headers when reading message begin": function(assert) { + const transport = new TFramedTransport(); + transport.inBuf = Buffer.from(headerPayload); + const protocol = new THeaderProtocol(transport); + const result = protocol.readMessageBegin(); + + const headers = transport.getReadHeaders(); + assert.equals(headers.Parent, "shoobar"); + assert.equals(headers.Trace, "abcde"); + assert.equals(result.fname, "add"); + assert.equals(result.mtype, thrift.Thrift.MessageType.CALL); + assert.end(); + }, + "Should be able to write headers": function(assert) { + const writeTransport = new TFramedTransport(); + writeTransport.setProtocolId(THeaderTransport.SubprotocolId.BINARY); + writeTransport.setWriteHeader("Hihihihi", "hohohoho"); + writeTransport.setWriteHeader("boobooboo", "fooshoopoo"); + writeTransport.setWriteHeader("a", "z"); + writeTransport.writeHeaders(); + const writeBuffer = writeTransport.outBuffers[0]; + + const readTransport = new TFramedTransport(); + readTransport.inBuf = writeBuffer; + readTransport.readHeaders(); + + const headers = readTransport.getReadHeaders(); + assert.equals(headers.Hihihihi, "hohohoho"); + assert.equals(headers.boobooboo, "fooshoopoo"); + assert.equals(headers.a, "z"); + assert.end(); + } +}; + +Object.keys(cases).forEach(function(caseName) { + test(caseName, cases[caseName]); +}); diff --git a/src/jaegertracing/thrift/lib/nodejs/test/helpers.js b/src/jaegertracing/thrift/lib/nodejs/test/helpers.js new file mode 100644 index 000000000..f3c27b3d1 --- /dev/null +++ b/src/jaegertracing/thrift/lib/nodejs/test/helpers.js @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +"use strict"; +const thrift = require("../lib/thrift"); + +module.exports.transports = { + buffered: thrift.TBufferedTransport, + framed: thrift.TFramedTransport +}; + +module.exports.protocols = { + json: thrift.TJSONProtocol, + binary: thrift.TBinaryProtocol, + compact: thrift.TCompactProtocol, + header: thrift.THeaderProtocol +}; + +module.exports.ecmaMode = process.argv.includes("--es6") ? "es6" : "es5"; +module.exports.genPath = process.argv.includes("--es6") + ? "gen-nodejs-es6" + : "gen-nodejs"; diff --git a/src/jaegertracing/thrift/lib/nodejs/test/int64.test.js b/src/jaegertracing/thrift/lib/nodejs/test/int64.test.js new file mode 100644 index 000000000..27ad28c00 --- /dev/null +++ b/src/jaegertracing/thrift/lib/nodejs/test/int64.test.js @@ -0,0 +1,92 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const Int64 = require("node-int64"); +const JSONInt64 = require("json-int64"); +const i64types = require("./gen-nodejs-es6/Int64Test_types.js"); +const test = require("tape"); + +const cases = { + "should correctly generate Int64 constants": function(assert) { + const EXPECTED_SMALL_INT64_AS_NUMBER = 42; + const EXPECTED_SMALL_INT64 = new Int64(42); + const EXPECTED_MAX_JS_SAFE_INT64 = new Int64(Number.MAX_SAFE_INTEGER); + const EXPECTED_MIN_JS_SAFE_INT64 = new Int64(Number.MIN_SAFE_INTEGER); + const EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64 = new Int64("0020000000000000"); // hex-encoded + const EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64 = new Int64("ffe0000000000000"); // hex-encoded 2's complement + const EXPECTED_MAX_SIGNED_INT64 = new Int64("7fffffffffffffff"); // hex-encoded + const EXPECTED_MIN_SIGNED_INT64 = new Int64("8000000000000000"); // hex-encoded 2's complement + const EXPECTED_INT64_LIST = [ + EXPECTED_SMALL_INT64, + EXPECTED_MAX_JS_SAFE_INT64, + EXPECTED_MIN_JS_SAFE_INT64, + EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64, + EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64, + EXPECTED_MAX_SIGNED_INT64, + EXPECTED_MIN_SIGNED_INT64 + ]; + + assert.ok(EXPECTED_SMALL_INT64.equals(i64types.SMALL_INT64)); + assert.ok(EXPECTED_MAX_JS_SAFE_INT64.equals(i64types.MAX_JS_SAFE_INT64)); + assert.ok(EXPECTED_MIN_JS_SAFE_INT64.equals(i64types.MIN_JS_SAFE_INT64)); + assert.ok( + EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64.equals( + i64types.MAX_JS_SAFE_PLUS_ONE_INT64 + ) + ); + assert.ok( + EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64.equals( + i64types.MIN_JS_SAFE_MINUS_ONE_INT64 + ) + ); + assert.ok(EXPECTED_MAX_SIGNED_INT64.equals(i64types.MAX_SIGNED_INT64)); + assert.ok(EXPECTED_MIN_SIGNED_INT64.equals(i64types.MIN_SIGNED_INT64)); + assert.equal( + EXPECTED_SMALL_INT64_AS_NUMBER, + i64types.SMALL_INT64.toNumber() + ); + assert.equal( + Number.MAX_SAFE_INTEGER, + i64types.MAX_JS_SAFE_INT64.toNumber() + ); + assert.equal( + Number.MIN_SAFE_INTEGER, + i64types.MIN_JS_SAFE_INT64.toNumber() + ); + + for (let i = 0; i < EXPECTED_INT64_LIST.length; ++i) { + assert.ok(EXPECTED_INT64_LIST[i].equals(i64types.INT64_LIST[i])); + } + + for (let i = 0; i < EXPECTED_INT64_LIST.length; ++i) { + const int64Object = EXPECTED_INT64_LIST[i]; + assert.ok( + i64types.INT64_2_INT64_MAP[ + JSONInt64.toDecimalString(int64Object) + ].equals(int64Object) + ); + } + + assert.end(); + } +}; + +Object.keys(cases).forEach(function(caseName) { + test(caseName, cases[caseName]); +}); diff --git a/src/jaegertracing/thrift/lib/nodejs/test/server.crt b/src/jaegertracing/thrift/lib/nodejs/test/server.crt new file mode 100644 index 000000000..8a5ef3c3a --- /dev/null +++ b/src/jaegertracing/thrift/lib/nodejs/test/server.crt @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIENzCCAx+gAwIBAgIJAOYfYfw7NCOcMA0GCSqGSIb3DQEBBQUAMIGxMQswCQYD +VQQGEwJVUzERMA8GA1UECAwITWFyeWxhbmQxFDASBgNVBAcMC0ZvcmVzdCBIaWxs +MScwJQYDVQQKDB5UaGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24xFjAUBgNV +BAsMDUFwYWNoZSBUaHJpZnQxEjAQBgNVBAMMCWxvY2FsaG9zdDEkMCIGCSqGSIb3 +DQEJARYVZGV2QHRocmlmdC5hcGFjaGUub3JnMB4XDTE0MDQwNzE4NTgwMFoXDTIy +MDYyNDE4NTgwMFowgbExCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhNYXJ5bGFuZDEU +MBIGA1UEBwwLRm9yZXN0IEhpbGwxJzAlBgNVBAoMHlRoZSBBcGFjaGUgU29mdHdh +cmUgRm91bmRhdGlvbjEWMBQGA1UECwwNQXBhY2hlIFRocmlmdDESMBAGA1UEAwwJ +bG9jYWxob3N0MSQwIgYJKoZIhvcNAQkBFhVkZXZAdGhyaWZ0LmFwYWNoZS5vcmcw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqE9TE9wEXp5LRtLQVDSGQ +GV78+7ZtP/I/ZaJ6Q6ZGlfxDFvZjFF73seNhAvlKlYm/jflIHYLnNOCySN8I2Xw6 +L9MbC+jvwkEKfQo4eDoxZnOZjNF5J1/lZtBeOowMkhhzBMH1Rds351/HjKNg6ZKg +2Cldd0j7HbDtEixOLgLbPRpBcaYrLrNMasf3Hal+x8/b8ue28x93HSQBGmZmMIUw +AinEu/fNP4lLGl/0kZb76TnyRpYSPYojtS6CnkH+QLYnsRREXJYwD1Xku62LipkX +wCkRTnZ5nUsDMX6FPKgjQFQCWDXG/N096+PRUQAChhrXsJ+gF3NqWtDmtrhVQF4n +AgMBAAGjUDBOMB0GA1UdDgQWBBQo8v0wzQPx3EEexJPGlxPK1PpgKjAfBgNVHSME +GDAWgBQo8v0wzQPx3EEexJPGlxPK1PpgKjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3 +DQEBBQUAA4IBAQBGFRiJslcX0aJkwZpzTwSUdgcfKbpvNEbCNtVohfQVTI4a/oN5 +U+yqDZJg3vOaOuiAZqyHcIlZ8qyesCgRN314Tl4/JQ++CW8mKj1meTgo5YFxcZYm +T9vsI3C+Nzn84DINgI9mx6yktIt3QOKZRDpzyPkUzxsyJ8J427DaimDrjTR+fTwD +1Dh09xeeMnSa5zeV1HEDyJTqCXutLetwQ/IyfmMBhIx+nvB5f67pz/m+Dv6V0r3I +p4HCcdnDUDGJbfqtoqsAATQQWO+WWuswB6mOhDbvPTxhRpZq6AkgWqv4S+u3M2GO +r5p9FrBgavAw5bKO54C0oQKpN/5fta5l6Ws0 +-----END CERTIFICATE----- diff --git a/src/jaegertracing/thrift/lib/nodejs/test/server.js b/src/jaegertracing/thrift/lib/nodejs/test/server.js new file mode 100644 index 000000000..7402094bc --- /dev/null +++ b/src/jaegertracing/thrift/lib/nodejs/test/server.js @@ -0,0 +1,137 @@ +#!/usr/bin/env node + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * 'License'); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const fs = require("fs"); +const path = require("path"); +const thrift = require("../lib/thrift"); +const program = require("commander"); +const helpers = require("./helpers"); + +program + .option( + "-p, --protocol <protocol>", + "Set thrift protocol (binary|compact|json)", + "binary" + ) + .option( + "-t, --transport <transport>", + "Set thrift transport (buffered|framed|http)", + "buffered" + ) + .option("--ssl", "use ssl transport") + .option("--port <port>", "Set thrift server port", 9090) + .option("--domain-socket <path>", "Set thift server unix domain socket") + .option( + "-t, --type <type>", + "Select server type (http|multiplex|tcp|websocket)", + "tcp" + ) + .option("--callback", "test with callback style functions") + .option("--es6", "Use es6 code") + .option("--es5", "Use es5 code") + .parse(process.argv); + +const ThriftTest = require(`./${helpers.genPath}/ThriftTest`); +const SecondService = require(`./${helpers.genPath}/SecondService`); +const { ThriftTestHandler } = require("./test_handler"); + +const port = program.port; +const domainSocket = program.domainSocket; +const ssl = program.ssl; + +let type = program.type; +if (program.transport === "http") { + program.transport = "buffered"; + type = "http"; +} + +let options = { + transport: helpers.transports[program.transport], + protocol: helpers.protocols[program.protocol] +}; + +if (type === "http" || type === "websocket") { + options.handler = ThriftTestHandler; + options.processor = ThriftTest; + + options = { + services: { "/test": options }, + cors: { + "*": true + } + }; +} + +let processor; +if (type === "multiplex") { + const SecondServiceHandler = { + secondtestString: function(thing, result) { + console.log('testString("' + thing + '")'); + result(null, 'testString("' + thing + '")'); + } + }; + + processor = new thrift.MultiplexedProcessor(); + + processor.registerProcessor( + "ThriftTest", + new ThriftTest.Processor(ThriftTestHandler) + ); + + processor.registerProcessor( + "SecondService", + new SecondService.Processor(SecondServiceHandler) + ); +} + +if (ssl) { + if ( + type === "tcp" || + type === "multiplex" || + type === "http" || + type === "websocket" + ) { + options.tls = { + key: fs.readFileSync(path.resolve(__dirname, "server.key")), + cert: fs.readFileSync(path.resolve(__dirname, "server.crt")) + }; + } +} + +let server; +if (type === "tcp") { + server = thrift.createServer(ThriftTest, ThriftTestHandler, options); +} else if (type === "multiplex") { + server = thrift.createMultiplexServer(processor, options); +} else if (type === "http" || type === "websocket") { + server = thrift.createWebServer(options); +} + +if (domainSocket) { + server.listen(domainSocket); +} else if ( + type === "tcp" || + type === "multiplex" || + type === "http" || + type === "websocket" +) { + server.listen(port); +} diff --git a/src/jaegertracing/thrift/lib/nodejs/test/server.key b/src/jaegertracing/thrift/lib/nodejs/test/server.key new file mode 100644 index 000000000..263cfce59 --- /dev/null +++ b/src/jaegertracing/thrift/lib/nodejs/test/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCqE9TE9wEXp5LR +tLQVDSGQGV78+7ZtP/I/ZaJ6Q6ZGlfxDFvZjFF73seNhAvlKlYm/jflIHYLnNOCy +SN8I2Xw6L9MbC+jvwkEKfQo4eDoxZnOZjNF5J1/lZtBeOowMkhhzBMH1Rds351/H +jKNg6ZKg2Cldd0j7HbDtEixOLgLbPRpBcaYrLrNMasf3Hal+x8/b8ue28x93HSQB +GmZmMIUwAinEu/fNP4lLGl/0kZb76TnyRpYSPYojtS6CnkH+QLYnsRREXJYwD1Xk +u62LipkXwCkRTnZ5nUsDMX6FPKgjQFQCWDXG/N096+PRUQAChhrXsJ+gF3NqWtDm +trhVQF4nAgMBAAECggEAW/y52YYW6ypROGbZ94DQpFV0kLO7qT8q0Ksxw5sPNaIt +fEPRIymDa8ikyHWJS5Oxmw84wo5jnJV26jaLmwe2Lupq7Xf1lqej8f5LJtuv7cQR +xfzp1vM65KJFFJHp6WqjGqJ6HSSZOpVDsnQYcXQjQCdpyAmaSWd3p+FqYSZ1mQmD +bFNI7jqpczWSZhTdotQ7p7Hn9TVCehflP3yGIB3bQ+wCcCB85dOBz201L+YgaIck +Sz43A4NvWaQIRLRDw7s9GW4jY5T0Jv282WIeAlVpVxLIwu48r4R4yGTIx9Ydowvq +57+Y5iPPjAXxu0V9t00oS3bYxDaKh2DUfc/5zowq8QKBgQDYNVPXmaG0aIH4vjQ9 +7fRdw/UDkYcQbn6CnglQOu77/S8ogQzpKCVJgJgkZNqOVtQMEPzekGEcLTbje1gU +8Bky2k+PL9UwbFy0emnOVh4rqrNXHsRvJcehNT/PRb5hjF3MUMFV/0iD4b+naFaE +jrSWiZ2ZXj2qfwAK52GFbtOuBQKBgQDJYQuGiY0r22E4waJmCSKczoBT3cwlVzWj +V2ljgA9RHLNTVkvNNYQLGu2qngFrtwpeaSnsMDerVG4wKAQWyCnYzxVrlnC4uDrJ +HXuFEltBWi9Ffbgfsnd3749AT0oBP1NT2tMleguyf5DFgjCR3VRJLdrVaaZ8row/ +LqKcFMqnOwKBgB+OIO99l7E584Y3VG6ZdSneOLtNmRXX2pT7tcZE465ZdHGH7Dd3 +SYHhx9K/+Xn+yDH+pLli/xlarAEldmSP6k2WuTfftlC78AfTOfAId5zN7CDR9791 +Fx67I9X/itq33tS8EIuZl57P6uXm/4GXRloWOa8xpvRkVsBApuYPl8t1AoGATQDS +y2sllDObBXzlgGbV2WgNIgSZ311toTv3jJiXQsjauW8yJRHln+l4H9mzaWDgkiFc +ang1kUoDqF5k0eFQPxtQcYdhKwEnWWfwp33RbzfxA32DPnubuzzbZhfrkHaKgnIW +cyor9uFYlm2l7ODZLfJez2RKyTplXnOSsmQw6akCgYAz3dj9Hskyj+HVJ+ht1OcE +c7ai/ESkSA7Vajp0tjJp0EKjW/zq8DvUSXOtcdnJgkKycFluLwbmnaN4txBds1C1 +Qr8Rt2sUCCBNZe1L6DHe3XBdbkJe9sgZVNTjtUSQrzy8UhvsCqG4YWeCu07Szcbc +rdPUV9/uQkdx8VrShxlD8A== +-----END PRIVATE KEY----- diff --git a/src/jaegertracing/thrift/lib/nodejs/test/test-cases.js b/src/jaegertracing/thrift/lib/nodejs/test/test-cases.js new file mode 100644 index 000000000..02c566fbf --- /dev/null +++ b/src/jaegertracing/thrift/lib/nodejs/test/test-cases.js @@ -0,0 +1,180 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +"use strict"; + +const helpers = require("./helpers"); +const ttypes = require(`./${helpers.genPath}/ThriftTest_types`); +const Int64 = require("node-int64"); + +//all Languages in UTF-8 +/*jshint -W100 */ +const stringTest = (module.exports.stringTest = + "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, " + + "Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, " + + "Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, " + + "বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, " + + "Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, " + + "Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, " + + "Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, " + + "Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, " + + "Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, " + + "Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, " + + "Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, " + + "ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, " + + "Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, " + + "Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa " + + "Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, مازِرونی, Bahasa " + + "Melayu, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, " + + "Norsk (nynorsk), Norsk (bokmål), Nouormand, Diné bizaad, " + + "Occitan, Иронау, Papiamentu, Deitsch, Polski, پنجابی, پښتو, " + + "Norfuk / Pitkern, Português, Runa Simi, Rumantsch, Romani, Română, " + + "Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple " + + "English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, " + + "Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, " + + "Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, " + + "Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, " + + "Bân-lâm-gú, 粵語"); +/*jshint +W100 */ + +const specialCharacters = (module.exports.specialCharacters = + 'quote: " backslash:' + + " forwardslash-escaped: / " + + " backspace: \b formfeed: \f newline: \n return: \r tab: " + + ' now-all-of-them-together: "\\/\b\n\r\t' + + " now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><" + + ' char-to-test-json-parsing: ]] "]] \\" }}}{ [[[ '); + +const mapTestInput = (module.exports.mapTestInput = { + a: "123", + "a b": "with spaces ", + same: "same", + "0": "numeric key", + longValue: stringTest, + stringTest: "long key" +}); + +const simple = [ + ["testVoid", undefined], + ["testString", "Test"], + ["testString", ""], + ["testString", stringTest], + ["testString", specialCharacters], + ["testBool", true], + ["testBool", false], + ["testByte", 1], + ["testByte", 0], + ["testByte", -1], + ["testByte", -127], + ["testI32", -1], + ["testDouble", -5.2098523], + ["testDouble", 7.012052175215044], + ["testEnum", ttypes.Numberz.ONE], + ["testI64", 5], + ["testI64", -5], + ["testI64", 734359738368], + ["testI64", -734359738368], + ["testI64", new Int64(new Buffer([0, 0x20, 0, 0, 0, 0, 0, 1]))], // 2^53+1 + [ + "testI64", + new Int64(new Buffer([0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])) + ], // -2^53-1 + ["testTypedef", 69] +]; + +const mapout = {}; +for (let i = 0; i < 5; ++i) { + mapout[i] = i - 10; +} + +const deep = [ + [ + "testList", + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] + ] +]; + +const deepUnordered = [ + ["testMap", mapout], + ["testSet", [1, 2, 3]], + ["testStringMap", mapTestInput] +]; + +const out = new ttypes.Xtruct({ + string_thing: "Zero", + byte_thing: 1, + i32_thing: -3, + i64_thing: 1000000 +}); + +const out2 = new ttypes.Xtruct2(); +out2.byte_thing = 1; +out2.struct_thing = out; +out2.i32_thing = 5; + +const crazy = new ttypes.Insanity({ + userMap: { "5": 5, "8": 8 }, + xtructs: [ + new ttypes.Xtruct({ + string_thing: "Goodbye4", + byte_thing: 4, + i32_thing: 4, + i64_thing: 4 + }), + new ttypes.Xtruct({ + string_thing: "Hello2", + byte_thing: 2, + i32_thing: 2, + i64_thing: 2 + }) + ] +}); + +const crazy2 = new ttypes.Insanity({ + userMap: { "5": 5, "8": 8 }, + xtructs: [ + { + string_thing: "Goodbye4", + byte_thing: 4, + i32_thing: 4, + i64_thing: 4 + }, + { + string_thing: "Hello2", + byte_thing: 2, + i32_thing: 2, + i64_thing: 2 + } + ] +}); + +const insanity = { + "1": { "2": crazy, "3": crazy }, + "2": { "6": { userMap: {}, xtructs: [] } } +}; + +module.exports.simple = simple; +module.exports.deep = deep; +module.exports.deepUnordered = deepUnordered; + +module.exports.out = out; +module.exports.out2 = out2; +module.exports.crazy = crazy; +module.exports.crazy2 = crazy2; +module.exports.insanity = insanity; diff --git a/src/jaegertracing/thrift/lib/nodejs/test/testAll.sh b/src/jaegertracing/thrift/lib/nodejs/test/testAll.sh new file mode 100755 index 000000000..3ae88b369 --- /dev/null +++ b/src/jaegertracing/thrift/lib/nodejs/test/testAll.sh @@ -0,0 +1,151 @@ +#! /bin/sh + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +if [ -n "${1}" ]; then + COVER=${1}; +fi + +DIR="$( cd "$( dirname "$0" )" && pwd )" + +EPISODIC_DIR=${DIR}/episodic-code-generation-test + +THRIFT_FILES_DIR=${DIR}/../../../test + +THRIFT_COMPILER=${DIR}/../../../compiler/cpp/thrift + +ISTANBUL="$DIR/../../../node_modules/istanbul/lib/cli.js" + +REPORT_PREFIX="${DIR}/../coverage/report" + +COUNT=0 + +export NODE_PATH="${DIR}:${DIR}/../lib:${NODE_PATH}" + +testServer() +{ + echo " [ECMA $1] Testing $2 Client/Server with protocol $3 and transport $4 $5"; + RET=0 + if [ -n "${COVER}" ]; then + ${ISTANBUL} cover ${DIR}/server.js --dir ${REPORT_PREFIX}${COUNT} --handle-sigint -- --type $2 -p $3 -t $4 $5 & + COUNT=$((COUNT+1)) + else + node ${DIR}/server.js --${1} --type $2 -p $3 -t $4 $5 & + fi + SERVERPID=$! + sleep 0.1 + if [ -n "${COVER}" ]; then + ${ISTANBUL} cover ${DIR}/client.js --dir ${REPORT_PREFIX}${COUNT} -- --${1} --type $2 -p $3 -t $4 $5 || RET=1 + COUNT=$((COUNT+1)) + else + node ${DIR}/client.js --${1} --type $2 -p $3 -t $4 $5 || RET=1 + fi + kill -2 $SERVERPID || RET=1 + wait $SERVERPID + return $RET +} + +testEpisodicCompilation() +{ + RET=0 + if [ -n "${COVER}" ]; then + ${ISTANBUL} cover ${EPISODIC_DIR}/server.js --dir ${REPORT_PREFIX}${COUNT} --handle-sigint & + COUNT=$((COUNT+1)) + else + node ${EPISODIC_DIR}/server.js & + fi + SERVERPID=$! + sleep 0.1 + if [ -n "${COVER}" ]; then + ${ISTANBUL} cover ${EPISODIC_DIR}/client.js --dir ${REPORT_PREFIX}${COUNT} || RET=1 + COUNT=$((COUNT+1)) + else + node ${EPISODIC_DIR}/client.js || RET=1 + fi + kill -2 $SERVERPID || RET=1 + wait $SERVERPID + return $RET +} + + +TESTOK=0 + +# generating Thrift code + +${THRIFT_COMPILER} -o ${DIR} --gen js:node ${THRIFT_FILES_DIR}/ThriftTest.thrift +${THRIFT_COMPILER} -o ${DIR} --gen js:node ${THRIFT_FILES_DIR}/JsDeepConstructorTest.thrift +${THRIFT_COMPILER} -o ${DIR} --gen js:node ${THRIFT_FILES_DIR}/Int64Test.thrift +mkdir ${DIR}/gen-nodejs-es6 +${THRIFT_COMPILER} -out ${DIR}/gen-nodejs-es6 --gen js:node,es6 ${THRIFT_FILES_DIR}/ThriftTest.thrift +${THRIFT_COMPILER} -out ${DIR}/gen-nodejs-es6 --gen js:node,es6 ${THRIFT_FILES_DIR}/JsDeepConstructorTest.thrift +${THRIFT_COMPILER} -out ${DIR}/gen-nodejs-es6 --gen js:node,es6 ${THRIFT_FILES_DIR}/Int64Test.thrift + +# generate episodic compilation test code +TYPES_PACKAGE=${EPISODIC_DIR}/node_modules/types-package + +# generate the first episode +mkdir --parents ${EPISODIC_DIR}/gen-1/first-episode +${THRIFT_COMPILER} -o ${EPISODIC_DIR}/gen-1/first-episode --gen js:node,thrift_package_output_directory=first-episode ${THRIFT_FILES_DIR}/Types.thrift + +# create a "package" from the first episode and "install" it, the episode file must be at the module root +mkdir --parents ${TYPES_PACKAGE}/first-episode +cp --force ${EPISODIC_DIR}/episodic_compilation.package.json ${TYPES_PACKAGE}/package.json +cp --force ${EPISODIC_DIR}/gen-1/first-episode/gen-nodejs/Types_types.js ${TYPES_PACKAGE}/first-episode/ +cp --force ${EPISODIC_DIR}/gen-1/first-episode/gen-nodejs/thrift.js.episode ${TYPES_PACKAGE} + +# generate the second episode +mkdir --parents ${EPISODIC_DIR}/gen-2/second-episode +${THRIFT_COMPILER} -o ${EPISODIC_DIR}/gen-2/second-episode --gen js:node,imports=${TYPES_PACKAGE} ${THRIFT_FILES_DIR}/Service.thrift +if [ -f ${EPISODIC_DIR}/gen-2/second-episode/Types_types.js ]; then + TESTOK=1 +fi + +# unit tests + +node ${DIR}/binary.test.js || TESTOK=1 +node ${DIR}/int64.test.js || TESTOK=1 +node ${DIR}/deep-constructor.test.js || TESTOK=1 + +# integration tests + +for type in tcp multiplex websocket http +do + for protocol in compact binary json + do + for transport in buffered framed + do + for ecma_version in es5 es6 + do + testServer $ecma_version $type $protocol $transport || TESTOK=1 + testServer $ecma_version $type $protocol $transport --ssl || TESTOK=1 + testServer $ecma_version $type $protocol $transport --callback || TESTOK=1 + done + done + done +done + +# episodic compilation test +testEpisodicCompilation + +if [ -n "${COVER}" ]; then + ${ISTANBUL} report --dir "${DIR}/../coverage" --include "${DIR}/../coverage/report*/coverage.json" lcov cobertura html + rm -r ${DIR}/../coverage/report*/* + rmdir ${DIR}/../coverage/report* +fi + +exit $TESTOK diff --git a/src/jaegertracing/thrift/lib/nodejs/test/test_driver.js b/src/jaegertracing/thrift/lib/nodejs/test/test_driver.js new file mode 100644 index 000000000..7c9a91914 --- /dev/null +++ b/src/jaegertracing/thrift/lib/nodejs/test/test_driver.js @@ -0,0 +1,361 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * 'License'); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// This is the Node.js test driver for the standard Apache Thrift +// test service. The driver invokes every function defined in the +// Thrift Test service with a representative range of parameters. +// +// The ThriftTestDriver function requires a client object +// connected to a server hosting the Thrift Test service and +// supports an optional callback function which is called with +// a status message when the test is complete. + +const test = require("tape"); + +const helpers = require("./helpers"); +const ttypes = require(`./${helpers.genPath}/ThriftTest_types`); +const TException = require("thrift").Thrift.TException; +const Int64 = require("node-int64"); +const testCases = require("./test-cases"); + +exports.ThriftTestDriver = function(client, callback) { + test( + "NodeJS Style Callback Client Tests", + { skip: helpers.ecmaMode === "es6" }, + function(assert) { + const checkRecursively = makeRecursiveCheck(assert); + + function makeAsserter(assertionFn) { + return function(c) { + const fnName = c[0]; + const expected = c[1]; + client[fnName](expected, function(err, actual) { + assert.error(err, fnName + ": no callback error"); + assertionFn(actual, expected, fnName); + }); + }; + } + + testCases.simple.forEach( + makeAsserter(function(a, e, m) { + if (a instanceof Int64) { + const e64 = e instanceof Int64 ? e : new Int64(e); + assert.deepEqual(a.buffer, e64.buffer, m); + } else { + assert.equal(a, e, m); + } + }) + ); + testCases.deep.forEach(makeAsserter(assert.deepEqual)); + testCases.deepUnordered.forEach( + makeAsserter(makeUnorderedDeepEqual(assert)) + ); + + const arr = []; + for (let i = 0; i < 256; ++i) { + arr[i] = 255 - i; + } + let buf = new Buffer(arr); + client.testBinary(buf, function(err, response) { + assert.error(err, "testBinary: no callback error"); + assert.equal(response.length, 256, "testBinary"); + assert.deepEqual(response, buf, "testBinary(Buffer)"); + }); + buf = new Buffer(arr); + client.testBinary(buf.toString("binary"), function(err, response) { + assert.error(err, "testBinary: no callback error"); + assert.equal(response.length, 256, "testBinary"); + assert.deepEqual(response, buf, "testBinary(string)"); + }); + + client.testMapMap(42, function(err, response) { + const expected = { + "4": { "1": 1, "2": 2, "3": 3, "4": 4 }, + "-4": { "-4": -4, "-3": -3, "-2": -2, "-1": -1 } + }; + assert.error(err, "testMapMap: no callback error"); + assert.deepEqual(expected, response, "testMapMap"); + }); + + client.testStruct(testCases.out, function(err, response) { + assert.error(err, "testStruct: no callback error"); + checkRecursively(testCases.out, response, "testStruct"); + }); + + client.testNest(testCases.out2, function(err, response) { + assert.error(err, "testNest: no callback error"); + checkRecursively(testCases.out2, response, "testNest"); + }); + + client.testInsanity(testCases.crazy, function(err, response) { + assert.error(err, "testInsanity: no callback error"); + checkRecursively(testCases.insanity, response, "testInsanity"); + }); + + client.testInsanity(testCases.crazy2, function(err, response) { + assert.error(err, "testInsanity2: no callback error"); + checkRecursively(testCases.insanity, response, "testInsanity2"); + }); + + client.testException("TException", function(err, response) { + assert.ok( + err instanceof TException, + "testException: correct error type" + ); + assert.ok(!response, "testException: no response"); + }); + + client.testException("Xception", function(err, response) { + assert.ok( + err instanceof ttypes.Xception, + "testException: correct error type" + ); + assert.ok(!response, "testException: no response"); + assert.equal(err.errorCode, 1001, "testException: correct error code"); + assert.equal( + "Xception", + err.message, + "testException: correct error message" + ); + }); + + client.testException("no Exception", function(err, response) { + assert.error(err, "testException: no callback error"); + assert.ok(!response, "testException: no response"); + }); + + client.testOneway(0, function(err, response) { + assert.error(err, "testOneway: no callback error"); + assert.strictEqual(response, undefined, "testOneway: void response"); + }); + + checkOffByOne(function(done) { + client.testI32(-1, function(err, response) { + assert.error(err, "checkOffByOne: no callback error"); + assert.equal(-1, response); + assert.end(); + done(); + }); + }, callback); + } + ); + + // ES6 does not support callback style + if (helpers.ecmaMode === "es6") { + checkOffByOne(done => done(), callback); + } +}; + +exports.ThriftTestDriverPromise = function(client, callback) { + test("Promise Client Tests", function(assert) { + const checkRecursively = makeRecursiveCheck(assert); + + function makeAsserter(assertionFn) { + return function(c) { + const fnName = c[0]; + const expected = c[1]; + client[fnName](expected) + .then(function(actual) { + assertionFn(actual, expected, fnName); + }) + .catch(() => assert.fail("fnName")); + }; + } + + testCases.simple.forEach( + makeAsserter(function(a, e, m) { + if (a instanceof Int64) { + const e64 = e instanceof Int64 ? e : new Int64(e); + assert.deepEqual(a.buffer, e64.buffer, m); + } else { + assert.equal(a, e, m); + } + }) + ); + testCases.deep.forEach(makeAsserter(assert.deepEqual)); + testCases.deepUnordered.forEach( + makeAsserter(makeUnorderedDeepEqual(assert)) + ); + + client + .testStruct(testCases.out) + .then(function(response) { + checkRecursively(testCases.out, response, "testStruct"); + }) + .catch(() => assert.fail("testStruct")); + + client + .testNest(testCases.out2) + .then(function(response) { + checkRecursively(testCases.out2, response, "testNest"); + }) + .catch(() => assert.fail("testNest")); + + client + .testInsanity(testCases.crazy) + .then(function(response) { + checkRecursively(testCases.insanity, response, "testInsanity"); + }) + .catch(() => assert.fail("testInsanity")); + + client + .testInsanity(testCases.crazy2) + .then(function(response) { + checkRecursively(testCases.insanity, response, "testInsanity2"); + }) + .catch(() => assert.fail("testInsanity2")); + + client + .testException("TException") + .then(function() { + assert.fail("testException: TException"); + }) + .catch(function(err) { + assert.ok(err instanceof TException); + }); + + client + .testException("Xception") + .then(function() { + assert.fail("testException: Xception"); + }) + .catch(function(err) { + assert.ok(err instanceof ttypes.Xception); + assert.equal(err.errorCode, 1001); + assert.equal("Xception", err.message); + }); + + client + .testException("no Exception") + .then(function(response) { + assert.equal(undefined, response); //void + }) + .catch(() => assert.fail("testException")); + + client + .testOneway(0) + .then(function(response) { + assert.strictEqual(response, undefined, "testOneway: void response"); + }) + .catch(() => assert.fail("testOneway: should not reject")); + + checkOffByOne(function(done) { + client + .testI32(-1) + .then(function(response) { + assert.equal(-1, response); + assert.end(); + done(); + }) + .catch(() => assert.fail("checkOffByOne")); + }, callback); + }); +}; + +// Helper Functions +// ========================================================= + +function makeRecursiveCheck(assert) { + return function(map1, map2, msg) { + const equal = checkRecursively(map1, map2); + + assert.ok(equal, msg); + + // deepEqual doesn't work with fields using node-int64 + function checkRecursively(map1, map2) { + if (typeof map1 !== "function" && typeof map2 !== "function") { + if (!map1 || typeof map1 !== "object") { + //Handle int64 types (which use node-int64 in Node.js JavaScript) + if ( + typeof map1 === "number" && + typeof map2 === "object" && + map2.buffer && + map2.buffer instanceof Buffer && + map2.buffer.length === 8 + ) { + const n = new Int64(map2.buffer); + return map1 === n.toNumber(); + } else { + return map1 == map2; + } + } else { + return Object.keys(map1).every(function(key) { + return checkRecursively(map1[key], map2[key]); + }); + } + } + } + }; +} + +function checkOffByOne(done, callback) { + const retry_limit = 30; + const retry_interval = 100; + let test_complete = false; + let retrys = 0; + + /** + * redo a simple test after the oneway to make sure we aren't "off by one" -- + * if the server treated oneway void like normal void, this next test will + * fail since it will get the void confirmation rather than the correct + * result. In this circumstance, the client will throw the exception: + * + * Because this is the last test against the server, when it completes + * the entire suite is complete by definition (the tests run serially). + */ + done(function() { + test_complete = true; + }); + + //We wait up to retry_limit * retry_interval for the test suite to complete + function TestForCompletion() { + if (test_complete && callback) { + callback("Server successfully tested!"); + } else { + if (++retrys < retry_limit) { + setTimeout(TestForCompletion, retry_interval); + } else if (callback) { + callback( + "Server test failed to complete after " + + (retry_limit * retry_interval) / 1000 + + " seconds" + ); + } + } + } + + setTimeout(TestForCompletion, retry_interval); +} + +function makeUnorderedDeepEqual(assert) { + return function(actual, expected, name) { + assert.equal(actual.length, expected.length, name); + for (const k in actual) { + let found = false; + for (const k2 in expected) { + if (actual[k] === expected[k2]) { + found = true; + } + } + if (!found) { + assert.fail("Unexpected value " + actual[k] + " with key " + k); + } + } + }; +} diff --git a/src/jaegertracing/thrift/lib/nodejs/test/test_handler.js b/src/jaegertracing/thrift/lib/nodejs/test/test_handler.js new file mode 100644 index 000000000..317a7c810 --- /dev/null +++ b/src/jaegertracing/thrift/lib/nodejs/test/test_handler.js @@ -0,0 +1,220 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * 'License'); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +//This is the server side Node test handler for the standard +// Apache Thrift test service. +const helpers = require("./helpers"); +const ttypes = require(`./${helpers.genPath}/ThriftTest_types`); +const TException = require("thrift").Thrift.TException; + +function makeSyncHandler() { + return function(thing) { + return thing; + }; +} + +const syncHandlers = { + testVoid: testVoid, + testMapMap: testMapMap, + testInsanity: testInsanity, + testMulti: testMulti, + testException: testException, + testMultiException: testMultiException, + testOneway: testOneway +}; + +function makeAsyncHandler(label) { + return function(thing, result) { + thing = syncHandlers[label](thing); + result(null, thing); + }; +} + +const asyncHandlers = { + testVoid: testVoidAsync, + testMulti: testMultiAsync, + testException: testExceptionAsync, + testMultiException: testMultiExceptionAsync, + testOneway: testOnewayAsync +}; + +const identityHandlers = [ + "testString", + "testBool", + "testByte", + "testI32", + "testI64", + "testDouble", + "testBinary", + "testStruct", + "testNest", + "testMap", + "testStringMap", + "testSet", + "testList", + "testEnum", + "testTypedef" +]; + +function testVoid() { + //console.log('testVoid()'); +} + +function testVoidAsync(result) { + result(testVoid()); +} + +function testMapMap() { + const mapmap = []; + const pos = []; + const neg = []; + for (let i = 1; i < 5; i++) { + pos[i] = i; + neg[-i] = -i; + } + mapmap[4] = pos; + mapmap[-4] = neg; + + return mapmap; +} + +function testInsanity(argument) { + //console.log('testInsanity('); + //console.log(argument); + //console.log(')'); + + const first_map = []; + const second_map = []; + + first_map[ttypes.Numberz.TWO] = argument; + first_map[ttypes.Numberz.THREE] = argument; + + const looney = new ttypes.Insanity(); + second_map[ttypes.Numberz.SIX] = looney; + + const insane = []; + insane[1] = first_map; + insane[2] = second_map; + + //console.log('insane result:'); + //console.log(insane); + return insane; +} + +function testMulti(arg0, arg1, arg2) { + //console.log('testMulti()'); + + const hello = new ttypes.Xtruct(); + hello.string_thing = "Hello2"; + hello.byte_thing = arg0; + hello.i32_thing = arg1; + hello.i64_thing = arg2; + return hello; +} + +function testMultiAsync(arg0, arg1, arg2, arg3, arg4, arg5, result) { + const hello = testMulti(arg0, arg1, arg2, arg3, arg4, arg5); + result(null, hello); +} + +function testException(arg) { + //console.log('testException('+arg+')'); + if (arg === "Xception") { + const x = new ttypes.Xception(); + x.errorCode = 1001; + x.message = arg; + throw x; + } else if (arg === "TException") { + throw new TException(arg); + } else { + return; + } +} + +function testExceptionAsync(arg, result) { + //console.log('testException('+arg+')'); + if (arg === "Xception") { + const x = new ttypes.Xception(); + x.errorCode = 1001; + x.message = arg; + result(x); + } else if (arg === "TException") { + result(new TException(arg)); + } else { + result(null); + } +} + +function testMultiException(arg0, arg1) { + //console.log('testMultiException(' + arg0 + ', ' + arg1 + ')'); + if (arg0 === "Xception") { + const x = new ttypes.Xception(); + x.errorCode = 1001; + x.message = "This is an Xception"; + throw x; + } else if (arg0 === "Xception2") { + const x2 = new ttypes.Xception2(); + x2.errorCode = 2002; + x2.struct_thing = new ttypes.Xtruct(); + x2.struct_thing.string_thing = "This is an Xception2"; + throw x2; + } + + const res = new ttypes.Xtruct(); + res.string_thing = arg1; + return res; +} + +function testMultiExceptionAsync(arg0, arg1, result) { + //console.log('testMultiException(' + arg0 + ', ' + arg1 + ')'); + if (arg0 === "Xception") { + const x = new ttypes.Xception(); + x.errorCode = 1001; + x.message = "This is an Xception"; + result(x); + } else if (arg0 === "Xception2") { + const x2 = new ttypes.Xception2(); + x2.errorCode = 2002; + x2.struct_thing = new ttypes.Xtruct(); + x2.struct_thing.string_thing = "This is an Xception2"; + result(x2); + } else { + const res = new ttypes.Xtruct(); + res.string_thing = arg1; + result(null, res); + } +} + +//console.log('testOneway(' + sleepFor + ') => JavaScript (like Rust) never sleeps!'); +function testOneway() {} + +function testOnewayAsync(sleepFor) { + testOneway(sleepFor); +} + +identityHandlers.forEach(function(label) { + syncHandlers[label] = makeSyncHandler(label); + asyncHandlers[label] = makeAsyncHandler(label); +}); + +["testMapMap", "testInsanity"].forEach(function(label) { + asyncHandlers[label] = makeAsyncHandler(label); +}); + +exports.ThriftTestHandler = asyncHandlers; diff --git a/src/jaegertracing/thrift/lib/nodejs/test/test_header_payload b/src/jaegertracing/thrift/lib/nodejs/test/test_header_payload Binary files differnew file mode 100644 index 000000000..22d5ef7a2 --- /dev/null +++ b/src/jaegertracing/thrift/lib/nodejs/test/test_header_payload |