From e79c300f09eb781bee5a2cc402bea0eb370ca2a4 Mon Sep 17 00:00:00 2001 From: radekg Date: Fri, 2 Jan 2015 17:12:45 +0100 Subject: [PATCH 1/3] JS: Binary protocol with unit tests. --- lib/js/src/thrift.js | 558 +++++++++++++++++++++++++++++++++++ lib/js/test/test-binary.html | 47 +++ lib/js/test/test-binary.js | 191 ++++++++++++ 3 files changed, 796 insertions(+) create mode 100644 lib/js/test/test-binary.html create mode 100644 lib/js/test/test-binary.js diff --git a/lib/js/src/thrift.js b/lib/js/src/thrift.js index 79c921c3b3d..6622c860968 100644 --- a/lib/js/src/thrift.js +++ b/lib/js/src/thrift.js @@ -1429,5 +1429,563 @@ Thrift.Multiplexer.prototype.createClient = function (serviceName, SCl, transpor return client; }; +/** + * Initializes a BinaryProtocol Implementation as a Wrapper for Thrift.Protocol + * @constructor + * @param {Thrift.Transport} transport - The transport to serialize to/from. + * @param {Object} args - object with configurable properties for the protocol. + * @classdesc Apache Thrift Protocols perform serialization which enables cross + * language RPC. The Protocol type is the JavaScript browser implementation + * of the Apache Thrift TBinaryProtocol. + * @example + * var protocol = new Thrift.BinaryProtocol(transport, { strictRead: true, strictWrite: true }); + */ +Thrift.BinaryProtocol = function(transport, args) { + var opts = args || {}; + this.buffer = []; + this.transport = transport; + this.buffer_read_offset = 0; + this.strictRead = ( typeof(opts.strictRead) !== 'undefined' && typeof(opts.strictRead) === 'boolean' ) ? opts.strictRead : false; + this.strictWrite = ( typeof(opts.strictWrite) !== 'undefined' && typeof(opts.strictWrite) === 'boolean' ) ? opts.strictWrite : false; +}; +Thrift.inherits(Thrift.BinaryProtocol, Thrift.Protocol, 'binaryProtocol'); + +Thrift.BinaryProtocol.VERSION_MASK = 0xffff0000; +Thrift.BinaryProtocol.VERSION_1 = 0x80010000; +Thrift.BinaryProtocol.TYPE_MASK = 0x000000ff; + +Thrift.BinaryProtocol.prototype = { + + /** + * Serializes the beginning of a Thrift RPC message. + * @param {string} name - The service method to call. + * @param {Thrift.MessageType} messageType - The type of method call. + * @param {number} seqid - The sequence number of this call (always 0 in Apache Thrift). + */ + writeMessageBegin: function(name, type, seqid) { + if (this.strictWrite) { + this.writeI16(VERSION_1 >> 16); + this.writeI16(type); + this.writeString(name); + this.writeI32(seqid); + } else { + this.writeString(name); + this.writeByte(type); + this.writeI32(seqid); + } + }, + + /** + * Serializes the end of a Thrift RPC message. + */ + writeMessageEnd: function() {}, + + /** + * Serializes the beginning of a struct. + * @param {string} name - The name of the struct. + */ + writeStructBegin: function(name) {}, + + /** + * Serializes the end of a struct. + */ + writeStructEnd: function() {}, + + /** + * Serializes the beginning of a struct field. + * @param {string} name - The name of the field. + * @param {Thrift.Protocol.Type} fieldType - The data type of the field. + * @param {number} fieldId - The field's unique identifier. + */ + writeFieldBegin: function(name, type, id) { + this.writeByte(type); + this.writeI16(id); + }, + + /** + * Serializes the end of a field. + */ + writeFieldEnd: function() {}, + + /** + * Serializes the end of the set of fields for a struct. + */ + writeFieldStop: function() { + this.writeByte(Thrift.Type.STOP); + }, + + /** + * Serializes the beginning of a map collection. + * @param {Thrift.Type} keyType - The data type of the key. + * @param {Thrift.Type} valType - The data type of the value. + * @param {number} [size] - The number of elements in the map (ignored). + */ + writeMapBegin: function(ktype, vtype, size) { + this.writeByte(ktype); + this.writeByte(vtype); + this.writeI32(size); + }, + + /** + * Serializes the end of a map. + */ + writeMapEnd: function() {}, + + /** + * Serializes the beginning of a list collection. + * @param {Thrift.Type} elemType - The data type of the elements. + * @param {number} size - The number of elements in the list. + */ + writeListBegin: function(etype, size) { + this.writeByte(etype); + this.writeI32(size); + }, + + /** + * Serializes the end of a list. + */ + writeListEnd: function() {}, + + /** + * Serializes the beginning of a set collection. + * @param {Thrift.Type} elemType - The data type of the elements. + * @param {number} size - The number of elements in the list. + */ + writeSetBegin: function(etype, size) { + this.writeByte(etype); + this.writeI32(size); + }, + + /** + * Serializes the end of a set. + */ + writeSetEnd: function() {}, + + /** Serializes a boolean */ + writeBool: function(bool) { + this.writeByte(bool ? 1 : 0); + }, + + /** Serializes a number */ + writeByte: function(byte) { + if ( byte <= Math.pow(2,31)*-1 || byte >= Math.pow(2,31) ) { + throw new Error(byte + " is incorrect for byte."); + } + this.buffer.push(byte); + }, + + /** Serializes a number (short) */ + writeI16: function(i16) { + if ( i16 < Math.pow(2,15)*-1 || i16 >= Math.pow(2,16) ) { + throw new Error(i16 + " is incorrect for i16."); + } + this.buffer.push( 255 & i16 >> 8 ); + this.buffer.push( 255 & i16 ); + }, + + /** Serializes a number (int) */ + writeI32: function(i32) { + if ( i32 <= Math.pow(2,31)*-1 || i32 >= Math.pow(2,31) ) { + throw new Error(i32 + " is incorrect for i32."); + } + this.buffer.push(255 & i32 >> 24); + this.buffer.push(255 & i32 >> 16); + this.buffer.push(255 & i32 >> 8); + this.buffer.push(255 & i32); + }, + + /** Serializes a number (long, for values over MAX_INTEGER, it will overflow) */ + writeI64: function(i64) { + if ( i64 <= Math.pow(2,63)*-1 || i64 >= Math.pow(2,64) ) { + throw new Error(i64 + " is incorrect for i64."); + } + // Although this is a correct way of packing a long int, + // the value will overflow if the number is higher than max int + var hi = (i64 & 0xffffffff00000000 >> 32); + var lo = i64 & 0x00000000ffffffff; + this.writeI32(hi); + this.writeI32(lo); + }, + + /** Serializes a number (double IEEE-754) */ + writeDouble: function(dub) { + // The code obtained from here: http://cautionsingularityahead.blogspot.nl/2010/04/javascript-and-ieee754-redux.html + // According to the comments by the author, this code has been included in an external library + // and it's available under MIT license. + var ebits = 11; + var fbits = 52; + var bias = (1 << (ebits - 1)) - 1; + // Compute sign, exponent, fraction + var s, e, f; + if (isNaN(dub)) { + e = (1 << bias) - 1; f = 1; s = 0; + } + else if (dub === Infinity || dub === -Infinity) { + e = (1 << bias) - 1; f = 0; s = (dub < 0) ? 1 : 0; + } + else if (dub === 0) { + e = 0; f = 0; s = (1 / dub === -Infinity) ? 1 : 0; + } + else { + s = dub < 0; + dub = Math.abs(dub); + if (dub >= Math.pow(2, 1 - bias)) { + var ln = Math.min(Math.floor(Math.log(dub) / Math.LN2), bias); + e = ln + bias; + f = dub * Math.pow(2, fbits - ln) - Math.pow(2, fbits); + } else { + e = 0; + f = dub / Math.pow(2, 1 - bias - fbits); + } + } + + // Pack sign, exponent, fraction + var i, bits = []; + for (i = fbits; i; i -= 1) { bits.push(f % 2 ? 1 : 0); f = Math.floor(f / 2); } + for (i = ebits; i; i -= 1) { bits.push(e % 2 ? 1 : 0); e = Math.floor(e / 2); } + bits.push(s ? 1 : 0); + bits.reverse(); + var str = bits.join(''); + + // Bits to bytes + while (str.length) { + this.buffer.push(parseInt(str.substring(0, 8), 2)); + str = str.substring(8); + } + }, + + /** Serializes a string */ + writeString: function(str) { + var s = this.encode_utf8(str); + var buf = new ArrayBuffer(s.length); + var bufView = new Uint8Array(buf); + this.writeI32( s.length ); + for (var i=0, strLen=s.length; i 0x7f) { + val = 0 - ((val - 1) ^ 0xff); + } + return { value: val }; + }, + + /** Returns the an object with a value property set to the + next value found in the protocol buffer */ + readI16: function() { + return { value: ( (this.readByte().value & 255) << 8 | this.readByte().value & 255 ) }; + }, + + /** Returns the an object with a value property set to the + next value found in the protocol buffer */ + readI32: function() { + return { value: ( (this.readByte().value & 255) << 24 | (this.readByte().value & 255) << 16 | (this.readByte().value & 255) << 8 | this.readByte().value & 255 ) }; + }, + + /** Returns the an object with a value property set to the + next value found in the protocol buffer */ + readI64: function() { + // Although this is a correct way of packing a long int, + // the value will overflow if the number is higher than max int + var i32_1 = this.readI32().value; + var i32_2 = this.readI32().value; + return { value: (i32_1 << 32 | i32_2) }; + }, + + /** Returns the an object with a value property set to the + next value found in the protocol buffer */ + readDouble: function() { + // The code obtained from here: http://cautionsingularityahead.blogspot.nl/2010/04/javascript-and-ieee754-redux.html + // According to the comments by the author, this code has been included in an external library + // and it's available under MIT license. + var ebits = 11; + var fbits = 52; + var bytes = this.readMultiple(8); + // Bytes to bits + var bits = []; + for (var i = bytes.length; i; i -= 1) { + var byte = bytes[i - 1]; + for (var j = 8; j; j -= 1) { + bits.push(byte % 2 ? 1 : 0); byte = byte >> 1; + } + } + bits.reverse(); + var str = bits.join(''); + // Unpack sign, exponent, fraction + var bias = (1 << (ebits - 1)) - 1; + var s = parseInt(str.substring(0, 1), 2) ? -1 : 1; + var e = parseInt(str.substring(1, 1 + ebits), 2); + var f = parseInt(str.substring(1 + ebits), 2); + // Produce number + if (e === (1 << ebits) - 1) { + return { value: (f !== 0 ? NaN : s * Infinity) }; + } else if (e > 0) { + return { value: (s * Math.pow(2, e - bias) * (1 + f / Math.pow(2, fbits))) }; + } else if (f !== 0) { + return { value: (s * Math.pow(2, -(bias-1)) * (f / Math.pow(2, fbits))) }; + } else { + return { value: (s * 0) }; + } + }, + + /** Returns the an object with a value property set to the + next value found in the protocol buffer */ + readString: function() { + var size = this.readI32().value; + var bytes = this.readMultiple(size); + var s = String.fromCharCode.apply(null, new Uint8Array(bytes)); + return { value: this.decode_utf8(s) }; + }, + + readBinary: function() { + var size = this.readI32().value; + return { value: this.readMultiple( size ) }; + }, + + /** Returns the an object with a value property set to the + next value found in the protocol buffer */ + readMultipleAsString: function(len) { + var bytes = this.readMultiple(len); + var s = String.fromCharCode.apply(null, new Uint8Array(bytes)); + return this.decode_utf8(s); + }, + + /** Returns the an object with a value property set to the + next value found in the protocol buffer */ + readMultiple: function(len) { + var buf = []; + for (var i=0; i 0) { + if (this.rstack.length > this.rpos[this.rpos.length - 1] + 1) { + this.rstack.pop(); + } + } + this.skip(ret.ktype); + this.skip(ret.vtype); + } + this.readMapEnd(); + return null; + case Thrift.Type.SET: + ret = this.readSetBegin(); + for (i = 0; i < ret.size; i++) { + this.skip(ret.etype); + } + this.readSetEnd(); + return null; + case Thrift.Type.LIST: + ret = this.readListBegin(); + for (i = 0; i < ret.size; i++) { + this.skip(ret.etype); + } + this.readListEnd(); + return null; + } + }, + + // utils: + + encode_utf8: function(s) { + return unescape(encodeURIComponent(s)); + }, + decode_utf8: function(s) { + return decodeURIComponent(escape(s)); + } +}; diff --git a/lib/js/test/test-binary.html b/lib/js/test/test-binary.html new file mode 100644 index 00000000000..5ba8cf86baa --- /dev/null +++ b/lib/js/test/test-binary.html @@ -0,0 +1,47 @@ + + + + + + Thrift BinaryProtocol: Unit Test + + + + + + + + + + + +

Thrift BinaryProtocol: Unit Test

+

+
+

+
+

+ Valid XHTML 1.0! +

+ + + diff --git a/lib/js/test/test-binary.js b/lib/js/test/test-binary.js new file mode 100644 index 00000000000..121a7faf26a --- /dev/null +++ b/lib/js/test/test-binary.js @@ -0,0 +1,191 @@ +/* + * 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. + */ + /* jshint -W100 */ + +/* + * JavaScript test suite for Thrift BinaryProtocol. + */ + +////////////////////////////////// +//BinaryProtocol tests + +var transport = new Thrift.Transport("/dummy"); + +module("BinaryProtocol JavaScript tests"); + + test("Boolean", function() { + var protocol = new Thrift.BinaryProtocol(transport); + protocol.writeBool( true ); + protocol.writeBool( false ); + equal(protocol.readBool().value, true); + equal(protocol.readBool().value, false); + }); + + test("I16", function() { + var value = 54321; + var protocol = new Thrift.BinaryProtocol(transport); + protocol.writeI16( value ); + equal(protocol.readI16().value, value); + }); + + test("I32", function() { + var value = 22832000; + var protocol = new Thrift.BinaryProtocol(transport); + protocol.writeI32( value ); + equal(protocol.readI32().value, value); + }); + + test("I64", function() { + var value = 22832000; + var protocol = new Thrift.BinaryProtocol(transport); + protocol.writeI64( value ); + equal(protocol.readI64().value, value); + }); + + test("Double", function() { + var value = 20.832; + var protocol = new Thrift.BinaryProtocol(transport); + protocol.writeDouble( value ); + equal(protocol.readDouble().value, value); + }); + + test("String, different (human) languages", function() { + var value1 = "zażółcić gęślą jaźń"; + var value2 = "Döner am Nürburgring"; + var value3 = "Да!"; + var protocol = new Thrift.BinaryProtocol(transport); + protocol.writeString( value1 ); + protocol.writeString( value2 ); + protocol.writeString( value3 ); + equal(protocol.readString().value, value1); + equal(protocol.readString().value, value2); + equal(protocol.readString().value, value3); + }); + + test("Struct with skip", function() { + var structName = "TestStruct"; + var fields = [ + { name: "field1", value: "Döner am Nürburgring", fieldType: Thrift.Type.STRING, fieldId: 0 }, + { name: "field2", value: 765345, fieldType: Thrift.Type.I32, fieldId: 1 }, + { name: "field3", value: false, fieldType: Thrift.Type.BOOL, fieldId: 2 } ]; + + var protocol = new Thrift.BinaryProtocol(transport); + protocol.writeStructBegin(structName); + fields.forEach(function(fieldDef) { + protocol.writeFieldBegin( fieldDef.name, fieldDef.fieldType, fieldDef.fieldId ); + switch (fieldDef.fieldType) { + case Thrift.Type.STRING: + protocol.writeString(fieldDef.value); + break; + case Thrift.Type.I32: + protocol.writeI32(fieldDef.value); + break; + case Thrift.Type.BOOL: + protocol.writeBool(fieldDef.value); + break; + } + protocol.writeFieldEnd(); + }); + protocol.writeFieldStop(); + protocol.writeStructEnd(); + + var readStructStart = protocol.readStructBegin(); + equal(readStructStart.fname, ''); + + var firstFieldData = protocol.readFieldBegin(); + equal(firstFieldData.fname, ''); + equal(firstFieldData.ftype, fields[0].fieldType); + equal(firstFieldData.fid, fields[0].fieldId); + var firstFieldValue = protocol.readString().value; + equal(firstFieldValue, fields[0].value); + protocol.readFieldEnd(); + + // skipping second field on read: + var secondFieldData = protocol.readFieldBegin(); + equal(secondFieldData.fname, ''); + equal(secondFieldData.ftype, fields[1].fieldType); + equal(secondFieldData.fid, fields[1].fieldId); + var skipped = protocol.skip( secondFieldData.ftype ); + equal(skipped.value, fields[1].value); + protocol.readFieldEnd(); + + var thirdFieldData = protocol.readFieldBegin(); + equal(thirdFieldData.fname, ''); + equal(thirdFieldData.ftype, fields[2].fieldType); + equal(thirdFieldData.fid, fields[2].fieldId); + var thirdFieldValue = protocol.readBool().value; + equal(thirdFieldValue, fields[2].value); + protocol.readFieldEnd(); + }); + + test("List", function() { + var structName = "TestStruct"; + var items = [1,2,3,4,5]; + var protocol = new Thrift.BinaryProtocol(transport); + protocol.writeStructBegin(structName); + protocol.writeFieldBegin("some_shorts", Thrift.Type.LIST, 0); + protocol.writeListBegin(Thrift.Type.I16, items.length); + items.forEach(function(i) { + protocol.writeI16(i); + }); + protocol.writeListEnd(); + protocol.writeFieldEnd(); + protocol.writeFieldStop(); + protocol.writeStructEnd(); + + var readStructStart = protocol.readStructBegin(); + equal(readStructStart.fname, ''); + + var firstFieldData = protocol.readFieldBegin(); + equal(firstFieldData.fname, ''); + equal(firstFieldData.ftype, Thrift.Type.LIST); + equal(firstFieldData.fid, 0); + + var listData = protocol.readListBegin(); + equal(listData.size, items.length); + equal(listData.etype, Thrift.Type.I16); + + var readItems = []; + for ( var i=0; i Date: Mon, 5 Jan 2015 20:28:23 +0100 Subject: [PATCH 2/3] Integrated TBinaryProtocol into grunt tests to present the PhantonJS issue. --- lib/js/Gruntfile.js | 10 +- lib/js/src/thrift.js | 13 +- lib/js/test/ThriftTest.thrift | 393 ++++++++++++++++++++++++++++++++++ 3 files changed, 411 insertions(+), 5 deletions(-) create mode 100644 lib/js/test/ThriftTest.thrift diff --git a/lib/js/Gruntfile.js b/lib/js/Gruntfile.js index 3298d5cf267..a504b6e6099 100644 --- a/lib/js/Gruntfile.js +++ b/lib/js/Gruntfile.js @@ -123,6 +123,13 @@ module.exports = function(grunt) { 'https://localhost:8089/testws.html' ] } + }, + ThriftBinaryProtocol: { + options: { + urls: [ + 'http://localhost:8088/test-binary.html' + ] + } } }, jshint: { @@ -150,12 +157,13 @@ module.exports = function(grunt) { grunt.registerTask('test', ['jshint', 'shell:InstallThriftJS', 'shell:InstallThriftNodeJSDep', 'shell:ThriftGen', 'external_daemon:ThriftTestServer', 'external_daemon:ThriftTestServer_TLS', 'qunit:ThriftJS', 'qunit:ThriftJS_TLS', - 'shell:ThriftGenJQ', 'qunit:ThriftJSJQ', 'qunit:ThriftJSJQ_TLS' + 'shell:ThriftGenJQ', 'qunit:ThriftJSJQ', 'qunit:ThriftJSJQ_TLS', 'qunit:ThriftBinaryProtocol' ]); grunt.registerTask('default', ['jshint', 'shell:InstallThriftJS', 'shell:InstallThriftNodeJSDep', 'shell:ThriftGen', 'external_daemon:ThriftTestServer', 'external_daemon:ThriftTestServer_TLS', 'qunit:ThriftJS', 'qunit:ThriftJS_TLS', 'shell:ThriftGenJQ', 'qunit:ThriftJSJQ', 'qunit:ThriftJSJQ_TLS', + 'qunit:ThriftBinaryProtocol', 'concat', 'uglify', 'jsdoc' ]); }; diff --git a/lib/js/src/thrift.js b/lib/js/src/thrift.js index 6622c860968..91c96a27667 100644 --- a/lib/js/src/thrift.js +++ b/lib/js/src/thrift.js @@ -1888,8 +1888,7 @@ Thrift.BinaryProtocol.prototype = { readString: function() { var size = this.readI32().value; var bytes = this.readMultiple(size); - var s = String.fromCharCode.apply(null, new Uint8Array(bytes)); - return { value: this.decode_utf8(s) }; + return { value: this.decode_utf8( this.stringFromByteArray(bytes) ) }; }, readBinary: function() { @@ -1901,8 +1900,7 @@ Thrift.BinaryProtocol.prototype = { next value found in the protocol buffer */ readMultipleAsString: function(len) { var bytes = this.readMultiple(len); - var s = String.fromCharCode.apply(null, new Uint8Array(bytes)); - return this.decode_utf8(s); + return this.decode_utf8( this.stringFromByteArray(bytes) ); }, /** Returns the an object with a value property set to the @@ -1985,6 +1983,13 @@ Thrift.BinaryProtocol.prototype = { }, decode_utf8: function(s) { return decodeURIComponent(escape(s)); + }, + stringFromByteArray: function(barr) { + try { + return String.fromCharCode.apply(null, new Uint8Array(barr)); + } catch (e) { + return String.fromCharCode.apply(null, barr); + } } }; diff --git a/lib/js/test/ThriftTest.thrift b/lib/js/test/ThriftTest.thrift new file mode 100644 index 00000000000..467968a0355 --- /dev/null +++ b/lib/js/test/ThriftTest.thrift @@ -0,0 +1,393 @@ +/* + * 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. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +namespace c_glib TTest +namespace java thrift.test +namespace cpp thrift.test +namespace rb Thrift.Test +namespace perl ThriftTest +namespace csharp Thrift.Test +namespace js ThriftTest +namespace st ThriftTest +namespace py ThriftTest +namespace py.twisted ThriftTest +namespace go thrifttest +namespace php ThriftTest +namespace delphi Thrift.Test +namespace cocoa ThriftTest +namespace lua ThriftTest + +// Presence of namespaces and sub-namespaces for which there is +// no generator should compile with warnings only +namespace noexist ThriftTest +namespace cpp.noexist ThriftTest + +namespace * thrift.test + +/** + * Docstring! + */ +enum Numberz +{ + ONE = 1, + TWO, + THREE, + FIVE = 5, + SIX, + EIGHT = 8 +} + +const Numberz myNumberz = Numberz.ONE; +// the following is expected to fail: +// const Numberz urNumberz = ONE; + +typedef i64 UserId + +struct Bonk +{ + 1: string message, + 2: i32 type +} + +typedef map MapType + +struct Bools { + 1: bool im_true, + 2: bool im_false, +} + +struct Xtruct +{ + 1: string string_thing, + 4: byte byte_thing, + 9: i32 i32_thing, + 11: i64 i64_thing +} + +struct Xtruct2 +{ + 1: byte byte_thing, + 2: Xtruct struct_thing, + 3: i32 i32_thing +} + +struct Xtruct3 +{ + 1: string string_thing, + 4: i32 changed, + 9: i32 i32_thing, + 11: i64 i64_thing +} + + +struct Insanity +{ + 1: map userMap, + 2: list xtructs +} + +struct CrazyNesting { + 1: string string_field, + 2: optional set set_field, + 3: required list< map,map>>>>> list_field, + 4: binary binary_field +} + +exception Xception { + 1: i32 errorCode, + 2: string message +} + +exception Xception2 { + 1: i32 errorCode, + 2: Xtruct struct_thing +} + +struct EmptyStruct {} + +struct OneField { + 1: EmptyStruct field +} + +service ThriftTest +{ + /** + * Prints "testVoid()" and returns nothing. + */ + void testVoid(), + + /** + * Prints 'testString("%s")' with thing as '%s' + * @param string thing - the string to print + * @return string - returns the string 'thing' + */ + string testString(1: string thing), + + /** + * Prints 'testByte("%d")' with thing as '%d' + * @param byte thing - the byte to print + * @return byte - returns the byte 'thing' + */ + byte testByte(1: byte thing), + + /** + * Prints 'testI32("%d")' with thing as '%d' + * @param i32 thing - the i32 to print + * @return i32 - returns the i32 'thing' + */ + i32 testI32(1: i32 thing), + + /** + * Prints 'testI64("%d")' with thing as '%d' + * @param i64 thing - the i64 to print + * @return i64 - returns the i64 'thing' + */ + i64 testI64(1: i64 thing), + + /** + * Prints 'testDouble("%f")' with thing as '%f' + * @param double thing - the double to print + * @return double - returns the double 'thing' + */ + double testDouble(1: double thing), + + /** + * Prints 'testBinary("%s")' where '%s' is a hex-formatted string of thing's data + * @param binary thing - the binary data to print + * @return binary - returns the binary 'thing' + */ + binary testBinary(1: binary thing), + + /** + * Prints 'testStruct("{%s}")' where thing has been formatted into a string of comma separated values + * @param Xtruct thing - the Xtruct to print + * @return Xtruct - returns the Xtruct 'thing' + */ + Xtruct testStruct(1: Xtruct thing), + + /** + * Prints 'testNest("{%s}")' where thing has been formatted into a string of the nested struct + * @param Xtruct2 thing - the Xtruct2 to print + * @return Xtruct2 - returns the Xtruct2 'thing' + */ + Xtruct2 testNest(1: Xtruct2 thing), + + /** + * Prints 'testMap("{%s")' where thing has been formatted into a string of 'key => value' pairs + * separated by commas and new lines + * @param map thing - the map to print + * @return map - returns the map 'thing' + */ + map testMap(1: map thing), + + /** + * Prints 'testStringMap("{%s}")' where thing has been formatted into a string of 'key => value' pairs + * separated by commas and new lines + * @param map thing - the map to print + * @return map - returns the map 'thing' + */ + map testStringMap(1: map thing), + + /** + * Prints 'testSet("{%s}")' where thing has been formatted into a string of values + * separated by commas and new lines + * @param set thing - the set to print + * @return set - returns the set 'thing' + */ + set testSet(1: set thing), + + /** + * Prints 'testList("{%s}")' where thing has been formatted into a string of values + * separated by commas and new lines + * @param list thing - the list to print + * @return list - returns the list 'thing' + */ + list testList(1: list thing), + + /** + * Prints 'testEnum("%d")' where thing has been formatted into it's numeric value + * @param Numberz thing - the Numberz to print + * @return Numberz - returns the Numberz 'thing' + */ + Numberz testEnum(1: Numberz thing), + + /** + * Prints 'testTypedef("%d")' with thing as '%d' + * @param UserId thing - the UserId to print + * @return UserId - returns the UserId 'thing' + */ + UserId testTypedef(1: UserId thing), + + /** + * Prints 'testMapMap("%d")' with hello as '%d' + * @param i32 hello - the i32 to print + * @return map> - returns a dictionary with these values: + * {-4 => {-4 => -4, -3 => -3, -2 => -2, -1 => -1, }, 4 => {1 => 1, 2 => 2, 3 => 3, 4 => 4, }, } + */ + map> testMapMap(1: i32 hello), + + /** + * So you think you've got this all worked, out eh? + * + * Creates a the returned map with these values and prints it out: + * { 1 => { 2 => argument, + * 3 => argument, + * }, + * 2 => { 6 => , }, + * } + * @return map> - a map with the above values + */ + map> testInsanity(1: Insanity argument), + + /** + * Prints 'testMulti()' + * @param byte arg0 - + * @param i32 arg1 - + * @param i64 arg2 - + * @param map arg3 - + * @param Numberz arg4 - + * @param UserId arg5 - + * @return Xtruct - returns an Xtruct with string_thing = "Hello2, byte_thing = arg0, i32_thing = arg1 + * and i64_thing = arg2 + */ + Xtruct testMulti(1: byte arg0, 2: i32 arg1, 3: i64 arg2, 4: map arg3, 5: Numberz arg4, 6: UserId arg5), + + /** + * Print 'testException(%s)' with arg as '%s' + * @param string arg - a string indication what type of exception to throw + * if arg == "Xception" throw Xception with errorCode = 1001 and message = arg + * elsen if arg == "TException" throw TException + * else do not throw anything + */ + void testException(1: string arg) throws(1: Xception err1), + + /** + * Print 'testMultiException(%s, %s)' with arg0 as '%s' and arg1 as '%s' + * @param string arg - a string indication what type of exception to throw + * if arg0 == "Xception" throw Xception with errorCode = 1001 and message = "This is an Xception" + * elsen if arg0 == "Xception2" throw Xception2 with errorCode = 2002 and message = "This is an Xception2" + * else do not throw anything + * @return Xtruct - an Xtruct with string_thing = arg1 + */ + Xtruct testMultiException(1: string arg0, 2: string arg1) throws(1: Xception err1, 2: Xception2 err2) + + /** + * Print 'testOneway(%d): Sleeping...' with secondsToSleep as '%d' + * sleep 'secondsToSleep' + * Print 'testOneway(%d): done sleeping!' with secondsToSleep as '%d' + * @param i32 secondsToSleep - the number of seconds to sleep + */ + oneway void testOneway(1:i32 secondsToSleep) +} + +service SecondService +{ + void blahBlah() + /** + * Prints 'testString("%s")' with thing as '%s' + * @param string thing - the string to print + * @return string - returns the string 'thing' + */ + string secondtestString(1: string thing), +} + +struct VersioningTestV1 { + 1: i32 begin_in_both, + 3: string old_string, + 12: i32 end_in_both +} + +struct VersioningTestV2 { + 1: i32 begin_in_both, + + 2: i32 newint, + 3: byte newbyte, + 4: i16 newshort, + 5: i64 newlong, + 6: double newdouble + 7: Bonk newstruct, + 8: list newlist, + 9: set newset, + 10: map newmap, + 11: string newstring, + 12: i32 end_in_both +} + +struct ListTypeVersioningV1 { + 1: list myints; + 2: string hello; +} + +struct ListTypeVersioningV2 { + 1: list strings; + 2: string hello; +} + +struct GuessProtocolStruct { + 7: map map_field, +} + +struct LargeDeltas { + 1: Bools b1, + 10: Bools b10, + 100: Bools b100, + 500: bool check_true, + 1000: Bools b1000, + 1500: bool check_false, + 2000: VersioningTestV2 vertwo2000, + 2500: set a_set2500, + 3000: VersioningTestV2 vertwo3000, + 4000: list big_numbers +} + +struct NestedListsI32x2 { + 1: list> integerlist +} +struct NestedListsI32x3 { + 1: list>> integerlist +} +struct NestedMixedx2 { + 1: list> int_set_list + 2: map> map_int_strset + 3: list>> map_int_strset_list +} +struct ListBonks { + 1: list bonk +} +struct NestedListsBonk { + 1: list>> bonk +} + +struct BoolTest { + 1: optional bool b = true; + 2: optional string s = "true"; +} + +struct StructA { + 1: required string s; +} + +struct StructB { + 1: optional StructA aa; + 2: required StructA ab; +} From ba711dad5508bd7941be918f213a47ea40cb059b Mon Sep 17 00:00:00 2001 From: radekg Date: Sun, 11 Jan 2015 02:22:49 +0100 Subject: [PATCH 3/3] Match protocol name and ctor to the nodejs one. --- lib/js/src/thrift.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/js/src/thrift.js b/lib/js/src/thrift.js index 91c96a27667..77713ff534e 100644 --- a/lib/js/src/thrift.js +++ b/lib/js/src/thrift.js @@ -1430,31 +1430,31 @@ Thrift.Multiplexer.prototype.createClient = function (serviceName, SCl, transpor }; /** - * Initializes a BinaryProtocol Implementation as a Wrapper for Thrift.Protocol + * Initializes a TBinaryProtocol Implementation as a Wrapper for Thrift.Protocol * @constructor * @param {Thrift.Transport} transport - The transport to serialize to/from. - * @param {Object} args - object with configurable properties for the protocol. + * @param {boolean} stringRead - indicates strict read. + * @param {boolean} stringWrite - indicates strict write. * @classdesc Apache Thrift Protocols perform serialization which enables cross * language RPC. The Protocol type is the JavaScript browser implementation * of the Apache Thrift TBinaryProtocol. * @example - * var protocol = new Thrift.BinaryProtocol(transport, { strictRead: true, strictWrite: true }); + * var protocol = new Thrift.TBinaryProtocol(transport, { strictRead: true, strictWrite: true }); */ -Thrift.BinaryProtocol = function(transport, args) { - var opts = args || {}; +Thrift.TBinaryProtocol = function(transport, strictRead, strictWrite) { this.buffer = []; this.transport = transport; this.buffer_read_offset = 0; - this.strictRead = ( typeof(opts.strictRead) !== 'undefined' && typeof(opts.strictRead) === 'boolean' ) ? opts.strictRead : false; - this.strictWrite = ( typeof(opts.strictWrite) !== 'undefined' && typeof(opts.strictWrite) === 'boolean' ) ? opts.strictWrite : false; + this.strictRead = (strictRead !== undefined ? strictRead : false); + this.strictWrite = (strictWrite !== undefined ? strictWrite : false); }; -Thrift.inherits(Thrift.BinaryProtocol, Thrift.Protocol, 'binaryProtocol'); +Thrift.inherits(Thrift.TBinaryProtocol, Thrift.Protocol, 'binaryProtocol'); -Thrift.BinaryProtocol.VERSION_MASK = 0xffff0000; -Thrift.BinaryProtocol.VERSION_1 = 0x80010000; -Thrift.BinaryProtocol.TYPE_MASK = 0x000000ff; +Thrift.TBinaryProtocol.VERSION_MASK = 0xffff0000; +Thrift.TBinaryProtocol.VERSION_1 = 0x80010000; +Thrift.TBinaryProtocol.TYPE_MASK = 0x000000ff; -Thrift.BinaryProtocol.prototype = { +Thrift.TBinaryProtocol.prototype = { /** * Serializes the beginning of a Thrift RPC message.