Adding mapbox-gl branch

This commit is contained in:
Andreas Hocevar
2015-03-16 18:50:27 +01:00
parent 7985f030fa
commit 57ee7f52fd
3109 changed files with 943365 additions and 0 deletions
@@ -0,0 +1,202 @@
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
//
// Licensed 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.
/**
* @fileoverview Protocol Buffer (Message) Descriptor class.
*/
goog.provide('goog.proto2.Descriptor');
goog.provide('goog.proto2.Metadata');
goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.object');
goog.require('goog.string');
/**
* @typedef {{name: (string|undefined),
* fullName: (string|undefined),
* containingType: (goog.proto2.Message|undefined)}}
*/
goog.proto2.Metadata;
/**
* A class which describes a Protocol Buffer 2 Message.
*
* @param {function(new:goog.proto2.Message)} messageType Constructor for
* the message class that this descriptor describes.
* @param {!goog.proto2.Metadata} metadata The metadata about the message that
* will be used to construct this descriptor.
* @param {Array<!goog.proto2.FieldDescriptor>} fields The fields of the
* message described by this descriptor.
*
* @constructor
* @final
*/
goog.proto2.Descriptor = function(messageType, metadata, fields) {
/**
* @type {function(new:goog.proto2.Message)}
* @private
*/
this.messageType_ = messageType;
/**
* @type {?string}
* @private
*/
this.name_ = metadata.name || null;
/**
* @type {?string}
* @private
*/
this.fullName_ = metadata.fullName || null;
/**
* @type {goog.proto2.Message|undefined}
* @private
*/
this.containingType_ = metadata.containingType;
/**
* The fields of the message described by this descriptor.
* @type {!Object<number, !goog.proto2.FieldDescriptor>}
* @private
*/
this.fields_ = {};
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
this.fields_[field.getTag()] = field;
}
};
/**
* Returns the name of the message, if any.
*
* @return {?string} The name.
*/
goog.proto2.Descriptor.prototype.getName = function() {
return this.name_;
};
/**
* Returns the full name of the message, if any.
*
* @return {?string} The name.
*/
goog.proto2.Descriptor.prototype.getFullName = function() {
return this.fullName_;
};
/**
* Returns the descriptor of the containing message type or null if none.
*
* @return {goog.proto2.Descriptor} The descriptor.
*/
goog.proto2.Descriptor.prototype.getContainingType = function() {
if (!this.containingType_) {
return null;
}
return this.containingType_.getDescriptor();
};
/**
* Returns the fields in the message described by this descriptor ordered by
* tag.
*
* @return {!Array<!goog.proto2.FieldDescriptor>} The array of field
* descriptors.
*/
goog.proto2.Descriptor.prototype.getFields = function() {
/**
* @param {!goog.proto2.FieldDescriptor} fieldA First field.
* @param {!goog.proto2.FieldDescriptor} fieldB Second field.
* @return {number} Negative if fieldA's tag number is smaller, positive
* if greater, zero if the same.
*/
function tagComparator(fieldA, fieldB) {
return fieldA.getTag() - fieldB.getTag();
};
var fields = goog.object.getValues(this.fields_);
goog.array.sort(fields, tagComparator);
return fields;
};
/**
* Returns the fields in the message as a key/value map, where the key is
* the tag number of the field. DO NOT MODIFY THE RETURNED OBJECT. We return
* the actual, internal, fields map for performance reasons, and changing the
* map can result in undefined behavior of this library.
*
* @return {!Object<number, !goog.proto2.FieldDescriptor>} The field map.
*/
goog.proto2.Descriptor.prototype.getFieldsMap = function() {
return this.fields_;
};
/**
* Returns the field matching the given name, if any. Note that
* this method searches over the *original* name of the field,
* not the camelCase version.
*
* @param {string} name The field name for which to search.
*
* @return {goog.proto2.FieldDescriptor} The field found, if any.
*/
goog.proto2.Descriptor.prototype.findFieldByName = function(name) {
var valueFound = goog.object.findValue(this.fields_,
function(field, key, obj) {
return field.getName() == name;
});
return /** @type {goog.proto2.FieldDescriptor} */ (valueFound) || null;
};
/**
* Returns the field matching the given tag number, if any.
*
* @param {number|string} tag The field tag number for which to search.
*
* @return {goog.proto2.FieldDescriptor} The field found, if any.
*/
goog.proto2.Descriptor.prototype.findFieldByTag = function(tag) {
goog.asserts.assert(goog.string.isNumeric(tag));
return this.fields_[parseInt(tag, 10)] || null;
};
/**
* Creates an instance of the message type that this descriptor
* describes.
*
* @return {!goog.proto2.Message} The instance of the message.
*/
goog.proto2.Descriptor.prototype.createMessageInstance = function() {
return new this.messageType_;
};
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<!--
Copyright 2008 The Closure Library Authors. All Rights Reserved.
Use of this source code is governed by the Apache License, Version 2.0.
See the COPYING file for details.
-->
<!--
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>
Closure Unit Tests - goog.proto2 - descriptor.js
</title>
<script src="../base.js">
</script>
<script>
goog.require('goog.proto2.DescriptorTest');
</script>
</head>
<body>
</body>
</html>
@@ -0,0 +1,78 @@
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
//
// Licensed 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.
goog.provide('goog.proto2.DescriptorTest');
goog.setTestOnly('goog.proto2.DescriptorTest');
goog.require('goog.proto2.Descriptor');
goog.require('goog.proto2.Message');
goog.require('goog.testing.jsunit');
function testDescriptorConstruction() {
var messageType = function() {};
var descriptor = new goog.proto2.Descriptor(messageType, {
name: 'test',
fullName: 'this.is.a.test'
}, []);
assertEquals('test', descriptor.getName());
assertEquals('this.is.a.test', descriptor.getFullName());
assertEquals(null, descriptor.getContainingType());
}
function testParentDescriptor() {
var parentType = function() {};
var messageType = function() {};
var parentDescriptor = new goog.proto2.Descriptor(parentType, {
name: 'parent',
fullName: 'this.is.a.parent'
}, []);
parentType.getDescriptor = function() {
return parentDescriptor;
};
var descriptor = new goog.proto2.Descriptor(messageType, {
name: 'test',
fullName: 'this.is.a.test',
containingType: parentType
}, []);
assertEquals(parentDescriptor, descriptor.getContainingType());
}
function testStaticGetDescriptorCachesResults() {
var messageType = function() {};
// This method would be provided by proto_library() BUILD rule.
messageType.prototype.getDescriptor = function() {
if (!messageType.descriptor_) {
// The descriptor is created lazily when we instantiate a new instance.
var descriptorObj = {
0: {
name: 'test',
fullName: 'this.is.a.test'
}
};
messageType.descriptor_ = goog.proto2.Message.createDescriptor(
messageType, descriptorObj);
}
return messageType.descriptor_;
};
messageType.getDescriptor = messageType.prototype.getDescriptor;
var descriptor = messageType.getDescriptor();
assertEquals(descriptor, messageType.getDescriptor()); // same instance
}
@@ -0,0 +1,306 @@
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
//
// Licensed 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.
/**
* @fileoverview Protocol Buffer Field Descriptor class.
*/
goog.provide('goog.proto2.FieldDescriptor');
goog.require('goog.asserts');
goog.require('goog.string');
/**
* A class which describes a field in a Protocol Buffer 2 Message.
*
* @param {function(new:goog.proto2.Message)} messageType Constructor for the
* message class to which the field described by this class belongs.
* @param {number|string} tag The field's tag index.
* @param {Object} metadata The metadata about this field that will be used
* to construct this descriptor.
*
* @constructor
* @final
*/
goog.proto2.FieldDescriptor = function(messageType, tag, metadata) {
/**
* The message type that contains the field that this
* descriptor describes.
* @private {function(new:goog.proto2.Message)}
*/
this.parent_ = messageType;
// Ensure that the tag is numeric.
goog.asserts.assert(goog.string.isNumeric(tag));
/**
* The field's tag number.
* @private {number}
*/
this.tag_ = /** @type {number} */ (tag);
/**
* The field's name.
* @private {string}
*/
this.name_ = metadata.name;
/** @type {goog.proto2.FieldDescriptor.FieldType} */
metadata.fieldType;
/** @type {*} */
metadata.repeated;
/** @type {*} */
metadata.required;
/** @type {*} */
metadata.packed;
/**
* If true, this field is a packed field.
* @private {boolean}
*/
this.isPacked_ = !!metadata.packed;
/**
* If true, this field is a repeating field.
* @private {boolean}
*/
this.isRepeated_ = !!metadata.repeated;
/**
* If true, this field is required.
* @private {boolean}
*/
this.isRequired_ = !!metadata.required;
/**
* The field type of this field.
* @private {goog.proto2.FieldDescriptor.FieldType}
*/
this.fieldType_ = metadata.fieldType;
/**
* If this field is a primitive: The native (ECMAScript) type of this field.
* If an enumeration: The enumeration object.
* If a message or group field: The Message function.
* @private {Function}
*/
this.nativeType_ = metadata.type;
/**
* Is it permissible on deserialization to convert between numbers and
* well-formed strings? Is true for 64-bit integral field types and float and
* double types, false for all other field types.
* @private {boolean}
*/
this.deserializationConversionPermitted_ = false;
switch (this.fieldType_) {
case goog.proto2.FieldDescriptor.FieldType.INT64:
case goog.proto2.FieldDescriptor.FieldType.UINT64:
case goog.proto2.FieldDescriptor.FieldType.FIXED64:
case goog.proto2.FieldDescriptor.FieldType.SFIXED64:
case goog.proto2.FieldDescriptor.FieldType.SINT64:
case goog.proto2.FieldDescriptor.FieldType.FLOAT:
case goog.proto2.FieldDescriptor.FieldType.DOUBLE:
this.deserializationConversionPermitted_ = true;
break;
}
/**
* The default value of this field, if different from the default, default
* value.
* @private {*}
*/
this.defaultValue_ = metadata.defaultValue;
};
/**
* An enumeration defining the possible field types.
* Should be a mirror of that defined in descriptor.h.
*
* @enum {number}
*/
goog.proto2.FieldDescriptor.FieldType = {
DOUBLE: 1,
FLOAT: 2,
INT64: 3,
UINT64: 4,
INT32: 5,
FIXED64: 6,
FIXED32: 7,
BOOL: 8,
STRING: 9,
GROUP: 10,
MESSAGE: 11,
BYTES: 12,
UINT32: 13,
ENUM: 14,
SFIXED32: 15,
SFIXED64: 16,
SINT32: 17,
SINT64: 18
};
/**
* Returns the tag of the field that this descriptor represents.
*
* @return {number} The tag number.
*/
goog.proto2.FieldDescriptor.prototype.getTag = function() {
return this.tag_;
};
/**
* Returns the descriptor describing the message that defined this field.
* @return {!goog.proto2.Descriptor} The descriptor.
*/
goog.proto2.FieldDescriptor.prototype.getContainingType = function() {
return this.parent_.getDescriptor();
};
/**
* Returns the name of the field that this descriptor represents.
* @return {string} The name.
*/
goog.proto2.FieldDescriptor.prototype.getName = function() {
return this.name_;
};
/**
* Returns the default value of this field.
* @return {*} The default value.
*/
goog.proto2.FieldDescriptor.prototype.getDefaultValue = function() {
if (this.defaultValue_ === undefined) {
// Set the default value based on a new instance of the native type.
// This will be (0, false, "") for (number, boolean, string) and will
// be a new instance of a group/message if the field is a message type.
var nativeType = this.nativeType_;
if (nativeType === Boolean) {
this.defaultValue_ = false;
} else if (nativeType === Number) {
this.defaultValue_ = 0;
} else if (nativeType === String) {
if (this.deserializationConversionPermitted_) {
// This field is a 64 bit integer represented as a string.
this.defaultValue_ = '0';
} else {
this.defaultValue_ = '';
}
} else {
return new nativeType;
}
}
return this.defaultValue_;
};
/**
* Returns the field type of the field described by this descriptor.
* @return {goog.proto2.FieldDescriptor.FieldType} The field type.
*/
goog.proto2.FieldDescriptor.prototype.getFieldType = function() {
return this.fieldType_;
};
/**
* Returns the native (i.e. ECMAScript) type of the field described by this
* descriptor.
*
* @return {Object} The native type.
*/
goog.proto2.FieldDescriptor.prototype.getNativeType = function() {
return this.nativeType_;
};
/**
* Returns true if simple conversions between numbers and strings are permitted
* during deserialization for this field.
*
* @return {boolean} Whether conversion is permitted.
*/
goog.proto2.FieldDescriptor.prototype.deserializationConversionPermitted =
function() {
return this.deserializationConversionPermitted_;
};
/**
* Returns the descriptor of the message type of this field. Only valid
* for fields of type GROUP and MESSAGE.
*
* @return {!goog.proto2.Descriptor} The message descriptor.
*/
goog.proto2.FieldDescriptor.prototype.getFieldMessageType = function() {
return this.nativeType_.getDescriptor();
};
/**
* @return {boolean} True if the field stores composite data or repeated
* composite data (message or group).
*/
goog.proto2.FieldDescriptor.prototype.isCompositeType = function() {
return this.fieldType_ == goog.proto2.FieldDescriptor.FieldType.MESSAGE ||
this.fieldType_ == goog.proto2.FieldDescriptor.FieldType.GROUP;
};
/**
* Returns whether the field described by this descriptor is packed.
* @return {boolean} Whether the field is packed.
*/
goog.proto2.FieldDescriptor.prototype.isPacked = function() {
return this.isPacked_;
};
/**
* Returns whether the field described by this descriptor is repeating.
* @return {boolean} Whether the field is repeated.
*/
goog.proto2.FieldDescriptor.prototype.isRepeated = function() {
return this.isRepeated_;
};
/**
* Returns whether the field described by this descriptor is required.
* @return {boolean} Whether the field is required.
*/
goog.proto2.FieldDescriptor.prototype.isRequired = function() {
return this.isRequired_;
};
/**
* Returns whether the field described by this descriptor is optional.
* @return {boolean} Whether the field is optional.
*/
goog.proto2.FieldDescriptor.prototype.isOptional = function() {
return !this.isRepeated_ && !this.isRequired_;
};
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<!--
Copyright 2008 The Closure Library Authors. All Rights Reserved.
Use of this source code is governed by the Apache License, Version 2.0.
See the COPYING file for details.
-->
<!--
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>
Closure Unit Tests - goog.proto2 - fielddescriptor.js
</title>
<script src="../base.js">
</script>
<script>
goog.require('goog.proto2.FieldDescriptorTest');
</script>
</head>
<body>
</body>
</html>
@@ -0,0 +1,139 @@
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
//
// Licensed 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.
goog.provide('goog.proto2.FieldDescriptorTest');
goog.setTestOnly('goog.proto2.FieldDescriptorTest');
goog.require('goog.proto2.FieldDescriptor');
goog.require('goog.proto2.Message');
goog.require('goog.testing.jsunit');
function testFieldDescriptorConstruction() {
var messageType = {};
var fieldDescriptor = new goog.proto2.FieldDescriptor(messageType, 10, {
name: 'test',
repeated: true,
packed: true,
fieldType: goog.proto2.FieldDescriptor.FieldType.INT32,
type: Number
});
assertEquals(10, fieldDescriptor.getTag());
assertEquals('test', fieldDescriptor.getName());
assertEquals(true, fieldDescriptor.isRepeated());
assertEquals(true, fieldDescriptor.isPacked());
assertEquals(goog.proto2.FieldDescriptor.FieldType.INT32,
fieldDescriptor.getFieldType());
assertEquals(Number, fieldDescriptor.getNativeType());
assertEquals(0, fieldDescriptor.getDefaultValue());
}
function testGetDefaultValueOfString() {
var fieldDescriptor = new goog.proto2.FieldDescriptor({}, 10, {
name: 'test',
fieldType: goog.proto2.FieldDescriptor.FieldType.STRING,
type: String
});
assertEquals('', fieldDescriptor.getDefaultValue());
}
function testGetDefaultValueOfBool() {
var fieldDescriptor = new goog.proto2.FieldDescriptor({}, 10, {
name: 'test',
fieldType: goog.proto2.FieldDescriptor.FieldType.BOOL,
type: Boolean
});
assertEquals(false, fieldDescriptor.getDefaultValue());
}
function testGetDefaultValueOfInt64() {
var fieldDescriptor = new goog.proto2.FieldDescriptor({}, 10, {
name: 'test',
fieldType: goog.proto2.FieldDescriptor.FieldType.INT64,
type: String
});
assertEquals('0', fieldDescriptor.getDefaultValue());
}
function testRepeatedField() {
var messageType = {};
var fieldDescriptor = new goog.proto2.FieldDescriptor(messageType, 10, {
name: 'test',
repeated: true,
fieldType: 7,
type: Number
});
assertEquals(true, fieldDescriptor.isRepeated());
assertEquals(false, fieldDescriptor.isRequired());
assertEquals(false, fieldDescriptor.isOptional());
}
function testRequiredField() {
var messageType = {};
var fieldDescriptor = new goog.proto2.FieldDescriptor(messageType, 10, {
name: 'test',
required: true,
fieldType: 7,
type: Number
});
assertEquals(false, fieldDescriptor.isRepeated());
assertEquals(true, fieldDescriptor.isRequired());
assertEquals(false, fieldDescriptor.isOptional());
}
function testOptionalField() {
var messageType = {};
var fieldDescriptor = new goog.proto2.FieldDescriptor(messageType, 10, {
name: 'test',
fieldType: 7,
type: Number
});
assertEquals(false, fieldDescriptor.isRepeated());
assertEquals(false, fieldDescriptor.isRequired());
assertEquals(true, fieldDescriptor.isOptional());
}
function testContaingType() {
var MessageType = function() {
MessageType.base(this, 'constructor');
};
goog.inherits(MessageType, goog.proto2.Message);
var descriptorObj = {
0: {
name: 'test_message',
fullName: 'this.is.a.test_message'
},
10: {
name: 'test',
fieldType: 7,
type: Number
}
};
goog.proto2.Message.set$Metadata(MessageType, descriptorObj);
var descriptor = MessageType.getDescriptor();
var fieldDescriptor = descriptor.getFields()[0];
assertEquals('10', fieldDescriptor.getTag());
assertEquals(descriptor, fieldDescriptor.getContainingType());
}
@@ -0,0 +1,70 @@
// Copyright 2009 The Closure Library Authors. All Rights Reserved.
//
// Licensed 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.
/**
* @fileoverview Base class for all PB2 lazy deserializer. A lazy deserializer
* is a serializer whose deserialization occurs on the fly as data is
* requested. In order to use a lazy deserializer, the serialized form
* of the data must be an object or array that can be indexed by the tag
* number.
*
*/
goog.provide('goog.proto2.LazyDeserializer');
goog.require('goog.asserts');
goog.require('goog.proto2.Message');
goog.require('goog.proto2.Serializer');
/**
* Base class for all lazy deserializers.
*
* @constructor
* @extends {goog.proto2.Serializer}
*/
goog.proto2.LazyDeserializer = function() {};
goog.inherits(goog.proto2.LazyDeserializer, goog.proto2.Serializer);
/** @override */
goog.proto2.LazyDeserializer.prototype.deserialize =
function(descriptor, data) {
var message = descriptor.createMessageInstance();
message.initializeForLazyDeserializer(this, data);
goog.asserts.assert(message instanceof goog.proto2.Message);
return message;
};
/** @override */
goog.proto2.LazyDeserializer.prototype.deserializeTo = function(message, data) {
throw new Error('Unimplemented');
};
/**
* Deserializes a message field from the expected format and places the
* data in the given message
*
* @param {goog.proto2.Message} message The message in which to
* place the information.
* @param {goog.proto2.FieldDescriptor} field The field for which to set the
* message value.
* @param {*} data The serialized data for the field.
*
* @return {*} The deserialized data or null for no value found.
*/
goog.proto2.LazyDeserializer.prototype.deserializeField = goog.abstractMethod;
@@ -0,0 +1,774 @@
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
//
// Licensed 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.
/**
* @fileoverview Protocol Buffer Message base class.
*/
goog.provide('goog.proto2.Message');
goog.require('goog.asserts');
goog.require('goog.proto2.Descriptor');
goog.require('goog.proto2.FieldDescriptor');
/**
* Abstract base class for all Protocol Buffer 2 messages. It will be
* subclassed in the code generated by the Protocol Compiler. Any other
* subclasses are prohibited.
* @constructor
*/
goog.proto2.Message = function() {
/**
* Stores the field values in this message. Keyed by the tag of the fields.
* @type {*}
* @private
*/
this.values_ = {};
/**
* Stores the field information (i.e. metadata) about this message.
* @type {Object<number, !goog.proto2.FieldDescriptor>}
* @private
*/
this.fields_ = this.getDescriptor().getFieldsMap();
/**
* The lazy deserializer for this message instance, if any.
* @type {goog.proto2.LazyDeserializer}
* @private
*/
this.lazyDeserializer_ = null;
/**
* A map of those fields deserialized, from tag number to their deserialized
* value.
* @type {Object}
* @private
*/
this.deserializedFields_ = null;
};
/**
* An enumeration defining the possible field types.
* Should be a mirror of that defined in descriptor.h.
*
* TODO(user): Remove this alias. The code generator generates code that
* references this enum, so it needs to exist until the code generator is
* changed. The enum was moved to from Message to FieldDescriptor to avoid a
* dependency cycle.
*
* Use goog.proto2.FieldDescriptor.FieldType instead.
*
* @enum {number}
*/
goog.proto2.Message.FieldType = {
DOUBLE: 1,
FLOAT: 2,
INT64: 3,
UINT64: 4,
INT32: 5,
FIXED64: 6,
FIXED32: 7,
BOOL: 8,
STRING: 9,
GROUP: 10,
MESSAGE: 11,
BYTES: 12,
UINT32: 13,
ENUM: 14,
SFIXED32: 15,
SFIXED64: 16,
SINT32: 17,
SINT64: 18
};
/**
* All instances of goog.proto2.Message should have a static descriptorObj_
* property. This is a JSON representation of a Descriptor. The real Descriptor
* will be deserialized lazily in the getDescriptor() method.
*
* This declaration is just here for documentation purposes.
* goog.proto2.Message does not have its own descriptor.
*
* TODO(user): Delete after components update for cl/76695317.
*
* @type {undefined}
* @private
*/
goog.proto2.Message.descriptorObj_;
/**
* All instances of goog.proto2.Message should have a static descriptor_
* property. The Descriptor will be deserialized lazily in the getDescriptor()
* method.
*
* This declaration is just here for documentation purposes.
* goog.proto2.Message does not have its own descriptor.
*
* @type {undefined}
* @private
*/
goog.proto2.Message.descriptor_;
/**
* Initializes the message with a lazy deserializer and its associated data.
* This method should be called by internal methods ONLY.
*
* @param {goog.proto2.LazyDeserializer} deserializer The lazy deserializer to
* use to decode the data on the fly.
*
* @param {*} data The data to decode/deserialize.
*/
goog.proto2.Message.prototype.initializeForLazyDeserializer = function(
deserializer, data) {
this.lazyDeserializer_ = deserializer;
this.values_ = data;
this.deserializedFields_ = {};
};
/**
* Sets the value of an unknown field, by tag.
*
* @param {number} tag The tag of an unknown field (must be >= 1).
* @param {*} value The value for that unknown field.
*/
goog.proto2.Message.prototype.setUnknown = function(tag, value) {
goog.asserts.assert(!this.fields_[tag],
'Field is not unknown in this message');
goog.asserts.assert(tag >= 1, 'Tag is not valid');
goog.asserts.assert(value !== null, 'Value cannot be null');
this.values_[tag] = value;
if (this.deserializedFields_) {
delete this.deserializedFields_[tag];
}
};
/**
* Iterates over all the unknown fields in the message.
*
* @param {function(number, *)} callback A callback method
* which gets invoked for each unknown field.
* @param {Object=} opt_scope The scope under which to execute the callback.
* If not given, the current message will be used.
*/
goog.proto2.Message.prototype.forEachUnknown = function(callback, opt_scope) {
var scope = opt_scope || this;
for (var key in this.values_) {
var keyNum = Number(key);
if (!this.fields_[keyNum]) {
callback.call(scope, keyNum, this.values_[key]);
}
}
};
/**
* Returns the descriptor which describes the current message.
*
* This only works if we assume people never subclass protobufs.
*
* TODO(user): Replace with goog.abstractMethod after components update
* with cl/76695317.
*
* @return {!goog.proto2.Descriptor} The descriptor.
*/
goog.proto2.Message.prototype.getDescriptor = function() {
// NOTE(nicksantos): These sorts of indirect references to descriptor
// through this.constructor are fragile. See the comments
// in set$Metadata for more info.
var Ctor = this.constructor;
return Ctor.descriptor_ ||
(Ctor.descriptor_ = goog.proto2.Message.createDescriptor(
Ctor, Ctor.descriptorObj_));
};
/**
* Returns whether there is a value stored at the field specified by the
* given field descriptor.
*
* @param {goog.proto2.FieldDescriptor} field The field for which to check
* if there is a value.
*
* @return {boolean} True if a value was found.
*/
goog.proto2.Message.prototype.has = function(field) {
goog.asserts.assert(
field.getContainingType() == this.getDescriptor(),
'The current message does not contain the given field');
return this.has$Value(field.getTag());
};
/**
* Returns the array of values found for the given repeated field.
*
* @param {goog.proto2.FieldDescriptor} field The field for which to
* return the values.
*
* @return {!Array<?>} The values found.
*/
goog.proto2.Message.prototype.arrayOf = function(field) {
goog.asserts.assert(
field.getContainingType() == this.getDescriptor(),
'The current message does not contain the given field');
return this.array$Values(field.getTag());
};
/**
* Returns the number of values stored in the given field.
*
* @param {goog.proto2.FieldDescriptor} field The field for which to count
* the number of values.
*
* @return {number} The count of the values in the given field.
*/
goog.proto2.Message.prototype.countOf = function(field) {
goog.asserts.assert(
field.getContainingType() == this.getDescriptor(),
'The current message does not contain the given field');
return this.count$Values(field.getTag());
};
/**
* Returns the value stored at the field specified by the
* given field descriptor.
*
* @param {goog.proto2.FieldDescriptor} field The field for which to get the
* value.
* @param {number=} opt_index If the field is repeated, the index to use when
* looking up the value.
*
* @return {*} The value found or null if none.
*/
goog.proto2.Message.prototype.get = function(field, opt_index) {
goog.asserts.assert(
field.getContainingType() == this.getDescriptor(),
'The current message does not contain the given field');
return this.get$Value(field.getTag(), opt_index);
};
/**
* Returns the value stored at the field specified by the
* given field descriptor or the default value if none exists.
*
* @param {goog.proto2.FieldDescriptor} field The field for which to get the
* value.
* @param {number=} opt_index If the field is repeated, the index to use when
* looking up the value.
*
* @return {*} The value found or the default if none.
*/
goog.proto2.Message.prototype.getOrDefault = function(field, opt_index) {
goog.asserts.assert(
field.getContainingType() == this.getDescriptor(),
'The current message does not contain the given field');
return this.get$ValueOrDefault(field.getTag(), opt_index);
};
/**
* Stores the given value to the field specified by the
* given field descriptor. Note that the field must not be repeated.
*
* @param {goog.proto2.FieldDescriptor} field The field for which to set
* the value.
* @param {*} value The new value for the field.
*/
goog.proto2.Message.prototype.set = function(field, value) {
goog.asserts.assert(
field.getContainingType() == this.getDescriptor(),
'The current message does not contain the given field');
this.set$Value(field.getTag(), value);
};
/**
* Adds the given value to the field specified by the
* given field descriptor. Note that the field must be repeated.
*
* @param {goog.proto2.FieldDescriptor} field The field in which to add the
* the value.
* @param {*} value The new value to add to the field.
*/
goog.proto2.Message.prototype.add = function(field, value) {
goog.asserts.assert(
field.getContainingType() == this.getDescriptor(),
'The current message does not contain the given field');
this.add$Value(field.getTag(), value);
};
/**
* Clears the field specified.
*
* @param {goog.proto2.FieldDescriptor} field The field to clear.
*/
goog.proto2.Message.prototype.clear = function(field) {
goog.asserts.assert(
field.getContainingType() == this.getDescriptor(),
'The current message does not contain the given field');
this.clear$Field(field.getTag());
};
/**
* Compares this message with another one ignoring the unknown fields.
* @param {*} other The other message.
* @return {boolean} Whether they are equal. Returns false if the {@code other}
* argument is a different type of message or not a message.
*/
goog.proto2.Message.prototype.equals = function(other) {
if (!other || this.constructor != other.constructor) {
return false;
}
var fields = this.getDescriptor().getFields();
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
var tag = field.getTag();
if (this.has$Value(tag) != other.has$Value(tag)) {
return false;
}
if (this.has$Value(tag)) {
var isComposite = field.isCompositeType();
var fieldsEqual = function(value1, value2) {
return isComposite ? value1.equals(value2) : value1 == value2;
};
var thisValue = this.getValueForTag_(tag);
var otherValue = other.getValueForTag_(tag);
if (field.isRepeated()) {
// In this case thisValue and otherValue are arrays.
if (thisValue.length != otherValue.length) {
return false;
}
for (var j = 0; j < thisValue.length; j++) {
if (!fieldsEqual(thisValue[j], otherValue[j])) {
return false;
}
}
} else if (!fieldsEqual(thisValue, otherValue)) {
return false;
}
}
}
return true;
};
/**
* Recursively copies the known fields from the given message to this message.
* Removes the fields which are not present in the source message.
* @param {!goog.proto2.Message} message The source message.
*/
goog.proto2.Message.prototype.copyFrom = function(message) {
goog.asserts.assert(this.constructor == message.constructor,
'The source message must have the same type.');
if (this != message) {
this.values_ = {};
if (this.deserializedFields_) {
this.deserializedFields_ = {};
}
this.mergeFrom(message);
}
};
/**
* Merges the given message into this message.
*
* Singular fields will be overwritten, except for embedded messages which will
* be merged. Repeated fields will be concatenated.
* @param {!goog.proto2.Message} message The source message.
*/
goog.proto2.Message.prototype.mergeFrom = function(message) {
goog.asserts.assert(this.constructor == message.constructor,
'The source message must have the same type.');
var fields = this.getDescriptor().getFields();
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
var tag = field.getTag();
if (message.has$Value(tag)) {
if (this.deserializedFields_) {
delete this.deserializedFields_[field.getTag()];
}
var isComposite = field.isCompositeType();
if (field.isRepeated()) {
var values = message.array$Values(tag);
for (var j = 0; j < values.length; j++) {
this.add$Value(tag, isComposite ? values[j].clone() : values[j]);
}
} else {
var value = message.getValueForTag_(tag);
if (isComposite) {
var child = this.getValueForTag_(tag);
if (child) {
child.mergeFrom(value);
} else {
this.set$Value(tag, value.clone());
}
} else {
this.set$Value(tag, value);
}
}
}
}
};
/**
* @return {!goog.proto2.Message} Recursive clone of the message only including
* the known fields.
*/
goog.proto2.Message.prototype.clone = function() {
/** @type {!goog.proto2.Message} */
var clone = new this.constructor;
clone.copyFrom(this);
return clone;
};
/**
* Fills in the protocol buffer with default values. Any fields that are
* already set will not be overridden.
* @param {boolean} simpleFieldsToo If true, all fields will be initialized;
* if false, only the nested messages and groups.
*/
goog.proto2.Message.prototype.initDefaults = function(simpleFieldsToo) {
var fields = this.getDescriptor().getFields();
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
var tag = field.getTag();
var isComposite = field.isCompositeType();
// Initialize missing fields.
if (!this.has$Value(tag) && !field.isRepeated()) {
if (isComposite) {
this.values_[tag] = new /** @type {Function} */ (field.getNativeType());
} else if (simpleFieldsToo) {
this.values_[tag] = field.getDefaultValue();
}
}
// Fill in the existing composite fields recursively.
if (isComposite) {
if (field.isRepeated()) {
var values = this.array$Values(tag);
for (var j = 0; j < values.length; j++) {
values[j].initDefaults(simpleFieldsToo);
}
} else {
this.get$Value(tag).initDefaults(simpleFieldsToo);
}
}
}
};
/**
* Returns the whether or not the field indicated by the given tag
* has a value.
*
* GENERATED CODE USE ONLY. Basis of the has{Field} methods.
*
* @param {number} tag The tag.
*
* @return {boolean} Whether the message has a value for the field.
*/
goog.proto2.Message.prototype.has$Value = function(tag) {
return this.values_[tag] != null;
};
/**
* Returns the value for the given tag number. If a lazy deserializer is
* instantiated, lazily deserializes the field if required before returning the
* value.
*
* @param {number} tag The tag number.
* @return {*} The corresponding value, if any.
* @private
*/
goog.proto2.Message.prototype.getValueForTag_ = function(tag) {
// Retrieve the current value, which may still be serialized.
var value = this.values_[tag];
if (!goog.isDefAndNotNull(value)) {
return null;
}
// If we have a lazy deserializer, then ensure that the field is
// properly deserialized.
if (this.lazyDeserializer_) {
// If the tag is not deserialized, then we must do so now. Deserialize
// the field's value via the deserializer.
if (!(tag in this.deserializedFields_)) {
var deserializedValue = this.lazyDeserializer_.deserializeField(
this, this.fields_[tag], value);
this.deserializedFields_[tag] = deserializedValue;
return deserializedValue;
}
return this.deserializedFields_[tag];
}
// Otherwise, just return the value.
return value;
};
/**
* Gets the value at the field indicated by the given tag.
*
* GENERATED CODE USE ONLY. Basis of the get{Field} methods.
*
* @param {number} tag The field's tag index.
* @param {number=} opt_index If the field is a repeated field, the index
* at which to get the value.
*
* @return {*} The value found or null for none.
* @protected
*/
goog.proto2.Message.prototype.get$Value = function(tag, opt_index) {
var value = this.getValueForTag_(tag);
if (this.fields_[tag].isRepeated()) {
var index = opt_index || 0;
goog.asserts.assert(
index >= 0 && index < value.length,
'Given index %s is out of bounds. Repeated field length: %s',
index, value.length);
return value[index];
}
return value;
};
/**
* Gets the value at the field indicated by the given tag or the default value
* if none.
*
* GENERATED CODE USE ONLY. Basis of the get{Field} methods.
*
* @param {number} tag The field's tag index.
* @param {number=} opt_index If the field is a repeated field, the index
* at which to get the value.
*
* @return {*} The value found or the default value if none set.
* @protected
*/
goog.proto2.Message.prototype.get$ValueOrDefault = function(tag, opt_index) {
if (!this.has$Value(tag)) {
// Return the default value.
var field = this.fields_[tag];
return field.getDefaultValue();
}
return this.get$Value(tag, opt_index);
};
/**
* Gets the values at the field indicated by the given tag.
*
* GENERATED CODE USE ONLY. Basis of the {field}Array methods.
*
* @param {number} tag The field's tag index.
*
* @return {!Array<*>} The values found. If none, returns an empty array.
* @protected
*/
goog.proto2.Message.prototype.array$Values = function(tag) {
var value = this.getValueForTag_(tag);
return /** @type {Array<*>} */ (value) || [];
};
/**
* Returns the number of values stored in the field by the given tag.
*
* GENERATED CODE USE ONLY. Basis of the {field}Count methods.
*
* @param {number} tag The tag.
*
* @return {number} The number of values.
* @protected
*/
goog.proto2.Message.prototype.count$Values = function(tag) {
var field = this.fields_[tag];
if (field.isRepeated()) {
return this.has$Value(tag) ? this.values_[tag].length : 0;
} else {
return this.has$Value(tag) ? 1 : 0;
}
};
/**
* Sets the value of the *non-repeating* field indicated by the given tag.
*
* GENERATED CODE USE ONLY. Basis of the set{Field} methods.
*
* @param {number} tag The field's tag index.
* @param {*} value The field's value.
* @protected
*/
goog.proto2.Message.prototype.set$Value = function(tag, value) {
if (goog.asserts.ENABLE_ASSERTS) {
var field = this.fields_[tag];
this.checkFieldType_(field, value);
}
this.values_[tag] = value;
if (this.deserializedFields_) {
this.deserializedFields_[tag] = value;
}
};
/**
* Adds the value to the *repeating* field indicated by the given tag.
*
* GENERATED CODE USE ONLY. Basis of the add{Field} methods.
*
* @param {number} tag The field's tag index.
* @param {*} value The value to add.
* @protected
*/
goog.proto2.Message.prototype.add$Value = function(tag, value) {
if (goog.asserts.ENABLE_ASSERTS) {
var field = this.fields_[tag];
this.checkFieldType_(field, value);
}
if (!this.values_[tag]) {
this.values_[tag] = [];
}
this.values_[tag].push(value);
if (this.deserializedFields_) {
delete this.deserializedFields_[tag];
}
};
/**
* Ensures that the value being assigned to the given field
* is valid.
*
* @param {!goog.proto2.FieldDescriptor} field The field being assigned.
* @param {*} value The value being assigned.
* @private
*/
goog.proto2.Message.prototype.checkFieldType_ = function(field, value) {
if (field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.ENUM) {
goog.asserts.assertNumber(value);
} else {
goog.asserts.assert(value.constructor == field.getNativeType());
}
};
/**
* Clears the field specified by tag.
*
* GENERATED CODE USE ONLY. Basis of the clear{Field} methods.
*
* @param {number} tag The tag of the field to clear.
* @protected
*/
goog.proto2.Message.prototype.clear$Field = function(tag) {
delete this.values_[tag];
if (this.deserializedFields_) {
delete this.deserializedFields_[tag];
}
};
/**
* Creates the metadata descriptor representing the definition of this message.
*
* @param {function(new:goog.proto2.Message)} messageType Constructor for the
* message type to which this metadata applies.
* @param {!Object} metadataObj The object containing the metadata.
* @return {!goog.proto2.Descriptor} The new descriptor.
*/
goog.proto2.Message.createDescriptor = function(messageType, metadataObj) {
var fields = [];
var descriptorInfo = metadataObj[0];
for (var key in metadataObj) {
if (key != 0) {
// Create the field descriptor.
fields.push(
new goog.proto2.FieldDescriptor(messageType, key, metadataObj[key]));
}
}
return new goog.proto2.Descriptor(messageType, descriptorInfo, fields);
};
/**
* Sets the metadata that represents the definition of this message.
*
* GENERATED CODE USE ONLY. Called when constructing message classes.
*
* TODO(user): Delete after components update with cl/76695317.
*
* @param {!Function} messageType Constructor for the
* message type to which this metadata applies.
* @param {Object} metadataObj The object containing the metadata.
*/
goog.proto2.Message.set$Metadata = function(messageType, metadataObj) {
// NOTE(nicksantos): JSCompiler's type-based optimizations really do not
// like indirectly defined methods (both prototype methods and
// static methods). This is very fragile in compiled code. I think it only
// really works by accident, and is highly likely to break in the future.
messageType.descriptorObj_ = metadataObj;
messageType.getDescriptor = function() {
// The descriptor is created lazily when we instantiate a new instance.
return messageType.descriptor_ ||
(new messageType()).getDescriptor();
};
};
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<!--
Copyright 2010 The Closure Library Authors. All Rights Reserved.
Use of this source code is governed by the Apache License, Version 2.0.
See the COPYING file for details.
-->
<!--
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>
Closure Unit Tests - goog.proto2 - message.js
</title>
<script src="../base.js">
</script>
<script>
goog.require('goog.proto2.MessageTest');
</script>
</head>
<body>
</body>
</html>
@@ -0,0 +1,466 @@
// Copyright 2010 The Closure Library Authors. All Rights Reserved.
//
// Licensed 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.
goog.provide('goog.proto2.MessageTest');
goog.setTestOnly('goog.proto2.MessageTest');
goog.require('goog.testing.jsunit');
goog.require('proto2.TestAllTypes');
goog.require('proto2.TestAllTypes.NestedEnum');
goog.require('proto2.TestAllTypes.NestedMessage');
goog.require('proto2.TestAllTypes.OptionalGroup');
goog.require('proto2.TestAllTypes.RepeatedGroup');
function testEqualsWithEmptyMessages() {
var message1 = new proto2.TestAllTypes();
assertTrue('same message object', message1.equals(message1));
assertFalse('comparison with null', message1.equals(null));
assertFalse('comparison with undefined', message1.equals(undefined));
var message2 = new proto2.TestAllTypes();
assertTrue('two empty message objects', message1.equals(message2));
var message3 = new proto2.TestAllTypes.NestedMessage();
assertFalse('different message types', message3.equals(message1));
}
function testEqualsWithSingleInt32Field() {
var message1 = new proto2.TestAllTypes();
var message2 = new proto2.TestAllTypes();
message1.setOptionalInt32(1);
assertFalse('message1 has an extra int32 field', message1.equals(message2));
message2.setOptionalInt32(1);
assertTrue('same int32 field in both messages', message1.equals(message2));
message2.setOptionalInt32(2);
assertFalse('different int32 field', message1.equals(message2));
message1.clearOptionalInt32();
assertFalse('message2 has an extra int32 field', message1.equals(message2));
}
function testEqualsWithRepeatedInt32Fields() {
var message1 = new proto2.TestAllTypes();
var message2 = new proto2.TestAllTypes();
message1.addRepeatedInt32(0);
message2.addRepeatedInt32(0);
assertTrue('equal repeated int32 field', message1.equals(message2));
message1.addRepeatedInt32(1);
assertFalse('message1 has more items', message1.equals(message2));
message2.addRepeatedInt32(1);
message2.addRepeatedInt32(1);
assertFalse('message2 has more items', message1.equals(message2));
message1.addRepeatedInt32(2);
assertFalse('different int32 items', message1.equals(message2));
}
function testEqualsWithDefaultValue() {
var message1 = new proto2.TestAllTypes();
var message2 = new proto2.TestAllTypes();
message1.setOptionalInt64('1');
assertEquals('message1.getOptionalInt64OrDefault should return 1',
'1', message1.getOptionalInt64OrDefault());
assertEquals('message2.getOptionalInt64OrDefault should return 1 too',
'1', message2.getOptionalInt64OrDefault());
assertTrue('message1.hasOptionalInt64() should be true',
message1.hasOptionalInt64());
assertFalse('message2.hasOptionalInt64() should be false',
message2.hasOptionalInt64());
assertFalse('as a result they are not equal', message1.equals(message2));
}
function testEqualsWithOptionalGroup() {
var message1 = new proto2.TestAllTypes();
var message2 = new proto2.TestAllTypes();
var group1 = new proto2.TestAllTypes.OptionalGroup();
var group2 = new proto2.TestAllTypes.OptionalGroup();
message1.setOptionalgroup(group1);
assertFalse('only message1 has OptionalGroup field',
message1.equals(message2));
message2.setOptionalgroup(group2);
assertTrue('both messages have OptionalGroup field',
message1.equals(message2));
group1.setA(0);
group2.setA(1);
assertFalse('different value in the optional group',
message1.equals(message2));
message1.clearOptionalgroup();
assertFalse('only message2 has OptionalGroup field',
message1.equals(message2));
}
function testEqualsWithRepeatedGroup() {
var message1 = new proto2.TestAllTypes();
var message2 = new proto2.TestAllTypes();
var group1 = new proto2.TestAllTypes.RepeatedGroup();
var group2 = new proto2.TestAllTypes.RepeatedGroup();
message1.addRepeatedgroup(group1);
assertFalse('message1 has more RepeatedGroups',
message1.equals(message2));
message2.addRepeatedgroup(group2);
assertTrue('both messages have one RepeatedGroup',
message1.equals(message2));
group1.addA(1);
assertFalse('message1 has more int32s in RepeatedGroup',
message1.equals(message2));
group2.addA(1);
assertTrue('both messages have one int32 in RepeatedGroup',
message1.equals(message2));
group1.addA(1);
group2.addA(2);
assertFalse('the messages have different int32s in RepeatedGroup',
message1.equals(message2));
}
function testEqualsWithNestedMessage() {
var message1 = new proto2.TestAllTypes();
var message2 = new proto2.TestAllTypes();
var nested1 = new proto2.TestAllTypes.NestedMessage();
var nested2 = new proto2.TestAllTypes.NestedMessage();
message1.setOptionalNestedMessage(nested1);
assertFalse('only message1 has nested message', message1.equals(message2));
message2.setOptionalNestedMessage(nested2);
assertTrue('both messages have nested message', message1.equals(message2));
nested1.setB(1);
assertFalse('different int32 in the nested messages',
message1.equals(message2));
message1.clearOptionalNestedMessage();
assertFalse('only message2 has nested message', message1.equals(message2));
}
function testEqualsWithNestedEnum() {
var message1 = new proto2.TestAllTypes();
var message2 = new proto2.TestAllTypes();
message1.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
assertFalse('only message1 has nested enum', message1.equals(message2));
message2.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
assertTrue('both messages have nested enum', message1.equals(message2));
message2.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.BAR);
assertFalse('different enum value', message1.equals(message2));
message1.clearOptionalNestedEnum();
assertFalse('only message2 has nested enum', message1.equals(message2));
}
function testEqualsWithUnknownFields() {
var message1 = new proto2.TestAllTypes();
var message2 = new proto2.TestAllTypes();
message1.setUnknown(999, 'foo');
message1.setUnknown(999, 'bar');
assertTrue('unknown fields are ignored', message1.equals(message2));
}
function testCloneEmptyMessage() {
var message = new proto2.TestAllTypes();
var clone = message.clone();
assertObjectEquals('cloned empty message', message, clone);
}
function testCloneMessageWithSeveralFields() {
var message = new proto2.TestAllTypes();
message.setOptionalInt32(1);
message.addRepeatedInt32(2);
var optionalGroup = new proto2.TestAllTypes.OptionalGroup();
optionalGroup.setA(3);
message.setOptionalgroup(optionalGroup);
var repeatedGroup = new proto2.TestAllTypes.RepeatedGroup();
repeatedGroup.addA(4);
message.addRepeatedgroup(repeatedGroup);
var nestedMessage = new proto2.TestAllTypes.NestedMessage();
nestedMessage.setB(5);
message.setOptionalNestedMessage(nestedMessage);
message.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
message.setUnknown(999, 'foo');
var clone = message.clone();
assertNotEquals('different OptionalGroup instance',
message.getOptionalgroup(), clone.getOptionalgroup());
assertNotEquals('different RepeatedGroup array instance',
message.repeatedgroupArray(), clone.repeatedgroupArray());
assertNotEquals('different RepeatedGroup array item instance',
message.getRepeatedgroup(0), clone.getRepeatedgroup(0));
assertNotEquals('different NestedMessage instance',
message.getOptionalNestedMessage(), clone.getOptionalNestedMessage());
}
function testCloneWithUnknownFields() {
var message = new proto2.TestAllTypes();
message.setUnknown(999, 'foo');
var clone = message.clone();
assertTrue('clone.equals(message) returns true', clone.equals(message));
clone.forEachUnknown(function(tag, value) {
fail('the unknown fields should not have been cloned');
});
clone.setUnknown(999, 'foo');
assertObjectEquals('the original and the cloned message are equal except ' +
'for the unknown fields', message, clone);
}
function testCopyFromSameMessage() {
var source = new proto2.TestAllTypes();
source.setOptionalInt32(32);
source.copyFrom(source);
assertEquals(32, source.getOptionalInt32());
}
function testCopyFromFlatMessage() {
// Recursive copying is implicitly tested in the testClone... methods.
var source = new proto2.TestAllTypes();
source.setOptionalInt32(32);
source.setOptionalInt64('64');
source.addRepeatedInt32(32);
var target = new proto2.TestAllTypes();
target.setOptionalInt32(33);
target.setOptionalUint32(33);
target.addRepeatedInt32(33);
target.copyFrom(source);
assertObjectEquals('source and target are equal after copyFrom', source,
target);
target.copyFrom(source);
assertObjectEquals('second copyFrom call has no effect', source, target);
source.setUnknown(999, 'foo');
target.setUnknown(999, 'bar');
target.copyFrom(source);
assertThrows('unknown fields are not copied',
goog.partial(assertObjectEquals, source, target));
}
function testMergeFromEmptyMessage() {
var source = new proto2.TestAllTypes();
source.setOptionalInt32(32);
source.setOptionalInt64('64');
var nested = new proto2.TestAllTypes.NestedMessage();
nested.setB(66);
source.setOptionalNestedMessage(nested);
var target = new proto2.TestAllTypes();
target.mergeFrom(source);
assertObjectEquals('source and target are equal after mergeFrom', source,
target);
}
function testMergeFromFlatMessage() {
var source = new proto2.TestAllTypes();
source.setOptionalInt32(32);
source.setOptionalString('foo');
source.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
var target = new proto2.TestAllTypes();
target.setOptionalInt64('64');
target.setOptionalString('bar');
target.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.BAR);
var expected = new proto2.TestAllTypes();
expected.setOptionalInt32(32);
expected.setOptionalInt64('64');
expected.setOptionalString('foo');
expected.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
target.mergeFrom(source);
assertObjectEquals('expected and target are equal after mergeFrom', expected,
target);
}
function testMergeFromNestedMessage() {
var source = new proto2.TestAllTypes();
var nested = new proto2.TestAllTypes.NestedMessage();
nested.setB(66);
source.setOptionalNestedMessage(nested);
var target = new proto2.TestAllTypes();
nested = new proto2.TestAllTypes.NestedMessage();
nested.setC(77);
target.setOptionalNestedMessage(nested);
var expected = new proto2.TestAllTypes();
nested = new proto2.TestAllTypes.NestedMessage();
nested.setB(66);
nested.setC(77);
expected.setOptionalNestedMessage(nested);
target.mergeFrom(source);
assertObjectEquals('expected and target are equal after mergeFrom', expected,
target);
}
function testMergeFromRepeatedMessage() {
var source = new proto2.TestAllTypes();
source.addRepeatedInt32(2);
source.addRepeatedInt32(3);
var target = new proto2.TestAllTypes();
target.addRepeatedInt32(1);
target.mergeFrom(source);
assertArrayEquals('repeated_int32 array has elements from both messages',
[1, 2, 3], target.repeatedInt32Array());
}
function testInitDefaultsWithEmptyMessage() {
var message = new proto2.TestAllTypes();
message.initDefaults(false);
assertFalse('int32 field is not set', message.hasOptionalInt32());
assertFalse('int64 [default=1] field is not set', message.hasOptionalInt64());
assertTrue('optional group field is set', message.hasOptionalgroup());
assertFalse('int32 inside the group is not set',
message.getOptionalgroup().hasA());
assertObjectEquals('value of the optional group',
new proto2.TestAllTypes.OptionalGroup(), message.getOptionalgroup());
assertTrue('nested message is set', message.hasOptionalNestedMessage());
assertObjectEquals('value of the nested message',
new proto2.TestAllTypes.NestedMessage(),
message.getOptionalNestedMessage());
assertFalse('nested enum is not set', message.hasOptionalNestedEnum());
assertFalse('repeated int32 is not set', message.hasRepeatedInt32());
assertFalse('repeated nested message is not set',
message.hasRepeatedNestedMessage());
message = new proto2.TestAllTypes();
message.initDefaults(true);
assertTrue('int32 field is set', message.hasOptionalInt32());
assertEquals('value of the int32 field', 0, message.getOptionalInt32());
assertTrue('int64 [default=1] field is set', message.hasOptionalInt64());
assertEquals('value of the int64 field', '1', message.getOptionalInt64());
assertTrue('int32 inside nested message is set',
message.getOptionalNestedMessage().hasB());
assertEquals('value of the int32 field inside the nested message', 0,
message.getOptionalNestedMessage().getB());
}
function testInitDefaultsWithNonEmptyMessage() {
var message = new proto2.TestAllTypes();
message.setOptionalInt32(32);
message.setOptionalInt64('64');
message.setOptionalgroup(new proto2.TestAllTypes.OptionalGroup());
var nested1 = new proto2.TestAllTypes.NestedMessage();
nested1.setB(66);
message.setOptionalNestedMessage(nested1);
var nested2 = new proto2.TestAllTypes.NestedMessage();
message.addRepeatedNestedMessage(nested2);
var nested3 = new proto2.TestAllTypes.NestedMessage();
nested3.setB(66);
message.addRepeatedNestedMessage(nested3);
message.initDefaults(true);
assertEquals('int32 field is unchanged', 32, message.getOptionalInt32());
assertEquals('int64 [default=1] field is unchanged', '64',
message.getOptionalInt64());
assertTrue('bool field is initialized', message.hasOptionalBool());
assertFalse('value of the bool field', message.getOptionalBool());
assertTrue('int32 inside the optional group is initialized',
message.getOptionalgroup().hasA());
assertEquals('value of the int32 inside the optional group', 0,
message.getOptionalgroup().getA());
assertEquals('int32 inside nested message is unchanged', 66,
message.getOptionalNestedMessage().getB());
assertTrue('int32 at index 0 of the repeated nested message is initialized',
message.getRepeatedNestedMessage(0).hasB());
assertEquals('value of int32 at index 0 of the repeated nested message', 0,
message.getRepeatedNestedMessage(0).getB());
assertEquals('int32 at index 1 of the repeated nested message is unchanged',
66, message.getRepeatedNestedMessage(1).getB());
}
function testInitDefaultsTwice() {
var message = new proto2.TestAllTypes();
message.initDefaults(false);
var clone = message.clone();
clone.initDefaults(false);
assertObjectEquals('second call of initDefaults(false) has no effect',
message, clone);
message = new proto2.TestAllTypes();
message.initDefaults(true);
clone = message.clone();
clone.initDefaults(true);
assertObjectEquals('second call of initDefaults(true) has no effect',
message, clone);
}
function testInitDefaultsThenClone() {
var message = new proto2.TestAllTypes();
message.initDefaults(true);
assertObjectEquals('message is cloned properly', message, message.clone());
}
function testClassGetDescriptorEqualToInstanceGetDescriptor() {
var classDescriptor = proto2.TestAllTypes.getDescriptor();
var instanceDescriptor = new proto2.TestAllTypes().getDescriptor();
assertEquals(classDescriptor, instanceDescriptor);
}
function testGetAfterSetWithLazyDeserializer() {
// Test makes sure that the lazy deserializer for a field is not
// erroneously called when get$Value is called after set$Value.
var message = new proto2.TestAllTypes();
var fakeDeserializer = {}; // stub with no methods defined; fails hard
message.initializeForLazyDeserializer(fakeDeserializer, {} /* data */);
message.setOptionalBool(true);
assertEquals(true, message.getOptionalBool());
}
function testHasOnLazyDeserializer() {
// Test that null values for fields are treated as absent by the lazy
// deserializer.
var message = new proto2.TestAllTypes();
var fakeDeserializer = {}; // stub with no methods defined; fails hard
message.initializeForLazyDeserializer(fakeDeserializer,
{13: false} /* data */);
assertEquals(true, message.hasOptionalBool());
}
function testHasOnLazyDeserializerWithNulls() {
// Test that null values for fields are treated as absent by the lazy
// deserializer.
var message = new proto2.TestAllTypes();
var fakeDeserializer = {}; // stub with no methods defined; fails hard
message.initializeForLazyDeserializer(fakeDeserializer,
{13: null} /* data */);
assertEquals(false, message.hasOptionalBool());
}
@@ -0,0 +1,176 @@
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
//
// Licensed 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.
/**
* @fileoverview Protocol Buffer 2 Serializer which serializes messages
* into anonymous, simplified JSON objects.
*
*/
goog.provide('goog.proto2.ObjectSerializer');
goog.require('goog.asserts');
goog.require('goog.proto2.FieldDescriptor');
goog.require('goog.proto2.Serializer');
goog.require('goog.string');
/**
* ObjectSerializer, a serializer which turns Messages into simplified
* ECMAScript objects.
*
* @param {goog.proto2.ObjectSerializer.KeyOption=} opt_keyOption If specified,
* which key option to use when serializing/deserializing.
* @constructor
* @extends {goog.proto2.Serializer}
*/
goog.proto2.ObjectSerializer = function(opt_keyOption) {
this.keyOption_ = opt_keyOption;
};
goog.inherits(goog.proto2.ObjectSerializer, goog.proto2.Serializer);
/**
* An enumeration of the options for how to emit the keys in
* the generated simplified object.
*
* @enum {number}
*/
goog.proto2.ObjectSerializer.KeyOption = {
/**
* Use the tag of the field as the key (default)
*/
TAG: 0,
/**
* Use the name of the field as the key. Unknown fields
* will still use their tags as keys.
*/
NAME: 1
};
/**
* Serializes a message to an object.
*
* @param {goog.proto2.Message} message The message to be serialized.
* @return {!Object} The serialized form of the message.
* @override
*/
goog.proto2.ObjectSerializer.prototype.serialize = function(message) {
var descriptor = message.getDescriptor();
var fields = descriptor.getFields();
var objectValue = {};
// Add the defined fields, recursively.
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
var key =
this.keyOption_ == goog.proto2.ObjectSerializer.KeyOption.NAME ?
field.getName() : field.getTag();
if (message.has(field)) {
if (field.isRepeated()) {
var array = [];
objectValue[key] = array;
for (var j = 0; j < message.countOf(field); j++) {
array.push(this.getSerializedValue(field, message.get(field, j)));
}
} else {
objectValue[key] = this.getSerializedValue(field, message.get(field));
}
}
}
// Add the unknown fields, if any.
message.forEachUnknown(function(tag, value) {
objectValue[tag] = value;
});
return objectValue;
};
/** @override */
goog.proto2.ObjectSerializer.prototype.getDeserializedValue =
function(field, value) {
// Gracefully handle the case where a boolean is represented by 0/1.
// Some serialization libraries, such as GWT, can use this notation.
if (field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.BOOL &&
goog.isNumber(value)) {
return Boolean(value);
}
return goog.proto2.ObjectSerializer.base(
this, 'getDeserializedValue', field, value);
};
/**
* Deserializes a message from an object and places the
* data in the message.
*
* @param {goog.proto2.Message} message The message in which to
* place the information.
* @param {*} data The data of the message.
* @override
*/
goog.proto2.ObjectSerializer.prototype.deserializeTo = function(message, data) {
var descriptor = message.getDescriptor();
for (var key in data) {
var field;
var value = data[key];
var isNumeric = goog.string.isNumeric(key);
if (isNumeric) {
field = descriptor.findFieldByTag(key);
} else {
// We must be in Key == NAME mode to lookup by name.
goog.asserts.assert(
this.keyOption_ == goog.proto2.ObjectSerializer.KeyOption.NAME);
field = descriptor.findFieldByName(key);
}
if (field) {
if (field.isRepeated()) {
goog.asserts.assert(goog.isArray(value));
for (var j = 0; j < value.length; j++) {
message.add(field, this.getDeserializedValue(field, value[j]));
}
} else {
goog.asserts.assert(!goog.isArray(value));
message.set(field, this.getDeserializedValue(field, value));
}
} else {
if (isNumeric) {
// We have an unknown field.
message.setUnknown(Number(key), value);
} else {
// Named fields must be present.
goog.asserts.fail('Failed to find field: ' + field);
}
}
}
};
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<!--
Copyright 2008 The Closure Library Authors. All Rights Reserved.
Use of this source code is governed by the Apache License, Version 2.0.
See the COPYING file for details.
-->
<!--
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>
Closure Unit Tests - goog.proto2 - objectserializer.js
</title>
<script src="../base.js">
</script>
<script>
goog.require('goog.proto2.ObjectSerializerTest');
</script>
</head>
<body>
</body>
</html>
@@ -0,0 +1,567 @@
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
//
// Licensed 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.
goog.provide('goog.proto2.ObjectSerializerTest');
goog.setTestOnly('goog.proto2.ObjectSerializerTest');
goog.require('goog.proto2.ObjectSerializer');
goog.require('goog.proto2.Serializer');
goog.require('goog.testing.PropertyReplacer');
goog.require('goog.testing.jsunit');
goog.require('proto2.TestAllTypes');
var propertyReplacer = new goog.testing.PropertyReplacer();
function tearDown() {
propertyReplacer.reset();
}
function testSerialization() {
var message = new proto2.TestAllTypes();
// Set the fields.
// Singular.
message.setOptionalInt32(101);
message.setOptionalInt64('102');
message.setOptionalUint32(103);
message.setOptionalUint64('104');
message.setOptionalSint32(105);
message.setOptionalSint64('106');
message.setOptionalFixed32(107);
message.setOptionalFixed64('108');
message.setOptionalSfixed32(109);
message.setOptionalSfixed64('110');
message.setOptionalFloat(111.5);
message.setOptionalDouble(112.5);
message.setOptionalBool(true);
message.setOptionalString('test');
message.setOptionalBytes('abcd');
var group = new proto2.TestAllTypes.OptionalGroup();
group.setA(111);
message.setOptionalgroup(group);
var nestedMessage = new proto2.TestAllTypes.NestedMessage();
nestedMessage.setB(112);
message.setOptionalNestedMessage(nestedMessage);
message.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
// Repeated.
message.addRepeatedInt32(201);
message.addRepeatedInt32(202);
// Serialize to a simplified object.
var simplified = new goog.proto2.ObjectSerializer().serialize(message);
// Assert that everything serialized properly.
assertEquals(101, simplified[1]);
assertEquals('102', simplified[2]);
assertEquals(103, simplified[3]);
assertEquals('104', simplified[4]);
assertEquals(105, simplified[5]);
assertEquals('106', simplified[6]);
assertEquals(107, simplified[7]);
assertEquals('108', simplified[8]);
assertEquals(109, simplified[9]);
assertEquals('110', simplified[10]);
assertEquals(111.5, simplified[11]);
assertEquals(112.5, simplified[12]);
assertEquals(true, simplified[13]);
assertEquals('test', simplified[14]);
assertEquals('abcd', simplified[15]);
assertEquals(111, simplified[16][17]);
assertEquals(112, simplified[18][1]);
assertEquals(proto2.TestAllTypes.NestedEnum.FOO, simplified[21]);
assertEquals(201, simplified[31][0]);
assertEquals(202, simplified[31][1]);
// Serialize to a simplified object (with key as name).
simplified = new goog.proto2.ObjectSerializer(
goog.proto2.ObjectSerializer.KeyOption.NAME).serialize(message);
// Assert that everything serialized properly.
assertEquals(101, simplified['optional_int32']);
assertEquals('102', simplified['optional_int64']);
assertEquals(103, simplified['optional_uint32']);
assertEquals('104', simplified['optional_uint64']);
assertEquals(105, simplified['optional_sint32']);
assertEquals('106', simplified['optional_sint64']);
assertEquals(107, simplified['optional_fixed32']);
assertEquals('108', simplified['optional_fixed64']);
assertEquals(109, simplified['optional_sfixed32']);
assertEquals('110', simplified['optional_sfixed64']);
assertEquals(111.5, simplified['optional_float']);
assertEquals(112.5, simplified['optional_double']);
assertEquals(true, simplified['optional_bool']);
assertEquals('test', simplified['optional_string']);
assertEquals('abcd', simplified['optional_bytes']);
assertEquals(111, simplified['optionalgroup']['a']);
assertEquals(112, simplified['optional_nested_message']['b']);
assertEquals(proto2.TestAllTypes.NestedEnum.FOO,
simplified['optional_nested_enum']);
assertEquals(201, simplified['repeated_int32'][0]);
assertEquals(202, simplified['repeated_int32'][1]);
}
function testSerializationOfUnknown() {
var message = new proto2.TestAllTypes();
// Set the fields.
// Known.
message.setOptionalInt32(101);
message.setOptionalInt64('102');
message.addRepeatedInt32(201);
message.addRepeatedInt32(202);
// Unknown.
message.setUnknown(1000, 301);
message.setUnknown(1001, 302);
// Serialize.
var simplified = new goog.proto2.ObjectSerializer().serialize(message);
assertEquals(101, simplified['1']);
assertEquals('102', simplified['2']);
assertEquals(201, simplified['31'][0]);
assertEquals(202, simplified['31'][1]);
assertEquals(301, simplified['1000']);
assertEquals(302, simplified['1001']);
}
function testDeserializationOfUnknown() {
var simplified = {
1: 101,
2: '102',
1000: 103,
1001: 104
};
var serializer = new goog.proto2.ObjectSerializer();
var message = serializer.deserialize(
proto2.TestAllTypes.getDescriptor(), simplified);
assertNotNull(message);
assertTrue(message.hasOptionalInt32());
assertTrue(message.hasOptionalInt64());
assertEquals(101, message.getOptionalInt32());
assertEquals('102', message.getOptionalInt64());
var count = 0;
message.forEachUnknown(function(tag, value) {
if (tag == 1000) {
assertEquals(103, value);
}
if (tag == 1001) {
assertEquals(104, value);
}
++count;
});
assertEquals(2, count);
}
function testDeserializationRepeated() {
var simplified = {
31: [101, 102],
41: [201.5, 202.5, 203.5],
42: [],
43: [true, false],
44: ['he', 'llo'],
46: [{ 47: [101] } , { 47: [102] }],
48: [{ 1: 201 }, { 1: 202 }]
};
var serializer = new goog.proto2.ObjectSerializer();
var message = serializer.deserialize(
proto2.TestAllTypes.getDescriptor(), simplified);
assertNotNull(message);
// Ensure the fields are set as expected.
assertTrue(message.hasRepeatedInt32());
assertTrue(message.hasRepeatedFloat());
assertFalse(message.hasRepeatedDouble());
assertTrue(message.hasRepeatedBool());
assertTrue(message.hasRepeatedgroup());
assertTrue(message.hasRepeatedNestedMessage());
// Ensure the counts match.
assertEquals(2, message.repeatedInt32Count());
assertEquals(3, message.repeatedFloatCount());
assertEquals(0, message.repeatedDoubleCount());
assertEquals(2, message.repeatedBoolCount());
assertEquals(2, message.repeatedStringCount());
assertEquals(2, message.repeatedgroupCount());
assertEquals(2, message.repeatedNestedMessageCount());
// Ensure the values match.
assertEquals(101, message.getRepeatedInt32(0));
assertEquals(102, message.getRepeatedInt32(1));
assertEquals(201.5, message.getRepeatedFloat(0));
assertEquals(202.5, message.getRepeatedFloat(1));
assertEquals(203.5, message.getRepeatedFloat(2));
assertEquals(true, message.getRepeatedBool(0));
assertEquals(false, message.getRepeatedBool(1));
assertEquals('he', message.getRepeatedString(0));
assertEquals('llo', message.getRepeatedString(1));
assertEquals(101, message.getRepeatedgroup(0).getA(0));
assertEquals(102, message.getRepeatedgroup(1).getA(0));
assertEquals(201, message.getRepeatedNestedMessage(0).getB());
assertEquals(202, message.getRepeatedNestedMessage(1).getB());
}
function testDeserialization() {
var simplified = {
1: 101,
2: '102',
3: 103,
4: '104',
5: 105,
6: '106',
7: 107,
8: '108',
9: 109,
10: '110',
11: 111.5,
12: 112.5,
13: true,
14: 'test',
15: 'abcd',
16: { 17 : 113 },
18: { 1 : 114 },
21: proto2.TestAllTypes.NestedEnum.FOO
};
var serializer = new goog.proto2.ObjectSerializer();
var message = serializer.deserialize(
proto2.TestAllTypes.getDescriptor(), simplified);
assertNotNull(message);
assertTrue(message.hasOptionalInt32());
assertTrue(message.hasOptionalInt64());
assertTrue(message.hasOptionalUint32());
assertTrue(message.hasOptionalUint64());
assertTrue(message.hasOptionalSint32());
assertTrue(message.hasOptionalSint64());
assertTrue(message.hasOptionalFixed32());
assertTrue(message.hasOptionalFixed64());
assertTrue(message.hasOptionalSfixed32());
assertTrue(message.hasOptionalSfixed64());
assertTrue(message.hasOptionalFloat());
assertTrue(message.hasOptionalDouble());
assertTrue(message.hasOptionalBool());
assertTrue(message.hasOptionalString());
assertTrue(message.hasOptionalBytes());
assertTrue(message.hasOptionalgroup());
assertTrue(message.hasOptionalNestedMessage());
assertTrue(message.hasOptionalNestedEnum());
assertEquals(1, message.optionalInt32Count());
assertEquals(1, message.optionalInt64Count());
assertEquals(1, message.optionalUint32Count());
assertEquals(1, message.optionalUint64Count());
assertEquals(1, message.optionalSint32Count());
assertEquals(1, message.optionalSint64Count());
assertEquals(1, message.optionalFixed32Count());
assertEquals(1, message.optionalFixed64Count());
assertEquals(1, message.optionalSfixed32Count());
assertEquals(1, message.optionalSfixed64Count());
assertEquals(1, message.optionalFloatCount());
assertEquals(1, message.optionalDoubleCount());
assertEquals(1, message.optionalBoolCount());
assertEquals(1, message.optionalStringCount());
assertEquals(1, message.optionalBytesCount());
assertEquals(1, message.optionalgroupCount());
assertEquals(1, message.optionalNestedMessageCount());
assertEquals(1, message.optionalNestedEnumCount());
assertEquals(101, message.getOptionalInt32());
assertEquals('102', message.getOptionalInt64());
assertEquals(103, message.getOptionalUint32());
assertEquals('104', message.getOptionalUint64());
assertEquals(105, message.getOptionalSint32());
assertEquals('106', message.getOptionalSint64());
assertEquals(107, message.getOptionalFixed32());
assertEquals('108', message.getOptionalFixed64());
assertEquals(109, message.getOptionalSfixed32());
assertEquals('110', message.getOptionalSfixed64());
assertEquals(111.5, message.getOptionalFloat());
assertEquals(112.5, message.getOptionalDouble());
assertEquals(true, message.getOptionalBool());
assertEquals('test', message.getOptionalString());
assertEquals('abcd', message.getOptionalBytes());
assertEquals(113, message.getOptionalgroup().getA());
assertEquals(114, message.getOptionalNestedMessage().getB());
assertEquals(proto2.TestAllTypes.NestedEnum.FOO,
message.getOptionalNestedEnum());
}
function testDeserializationUnknownEnumValue() {
var simplified = {
21: 1001
};
var serializer = new goog.proto2.ObjectSerializer();
var message = serializer.deserialize(
proto2.TestAllTypes.getDescriptor(), simplified);
assertNotNull(message);
assertEquals(1001, message.getOptionalNestedEnum());
}
function testDeserializationSymbolicEnumValue() {
var simplified = {
21: 'BAR'
};
propertyReplacer.set(goog.proto2.Serializer, 'DECODE_SYMBOLIC_ENUMS', true);
var serializer = new goog.proto2.ObjectSerializer();
var message = serializer.deserialize(
proto2.TestAllTypes.getDescriptor(), simplified);
assertNotNull(message);
assertEquals(proto2.TestAllTypes.NestedEnum.BAR,
message.getOptionalNestedEnum());
}
function testDeserializationSymbolicEnumValueTurnedOff() {
var simplified = {
21: 'BAR'
};
var serializer = new goog.proto2.ObjectSerializer();
assertThrows('Should have an assertion failure in deserialization',
function() {
serializer.deserialize(proto2.TestAllTypes.getDescriptor(), simplified);
});
}
function testDeserializationUnknownSymbolicEnumValue() {
var simplified = {
21: 'BARRED'
};
var serializer = new goog.proto2.ObjectSerializer();
assertThrows('Should have an assertion failure in deserialization',
function() {
serializer.deserialize(proto2.TestAllTypes.getDescriptor(), simplified);
});
}
function testDeserializationNumbersOrStrings() {
// 64-bit types may have been serialized as numbers or strings.
// Deserialization should be able to handle either.
var simplifiedWithNumbers = {
50: 5000,
51: 5100,
52: [5200, 5201],
53: [5300, 5301]
};
var simplifiedWithStrings = {
50: '5000',
51: '5100',
52: ['5200', '5201'],
53: ['5300', '5301']
};
var serializer = new goog.proto2.ObjectSerializer();
var message = serializer.deserialize(
proto2.TestAllTypes.getDescriptor(), simplifiedWithNumbers);
assertNotNull(message);
assertEquals(5000, message.getOptionalInt64Number());
assertEquals('5100', message.getOptionalInt64String());
assertEquals(5200, message.getRepeatedInt64Number(0));
assertEquals(5201, message.getRepeatedInt64Number(1));
assertEquals('5300', message.getRepeatedInt64String(0));
assertEquals('5301', message.getRepeatedInt64String(1));
assertArrayEquals([5200, 5201], message.repeatedInt64NumberArray());
assertArrayEquals(['5300', '5301'], message.repeatedInt64StringArray());
message = serializer.deserialize(
proto2.TestAllTypes.getDescriptor(), simplifiedWithStrings);
assertNotNull(message);
assertEquals(5000, message.getOptionalInt64Number());
assertEquals('5100', message.getOptionalInt64String());
assertEquals(5200, message.getRepeatedInt64Number(0));
assertEquals(5201, message.getRepeatedInt64Number(1));
assertEquals('5300', message.getRepeatedInt64String(0));
assertEquals('5301', message.getRepeatedInt64String(1));
assertArrayEquals([5200, 5201], message.repeatedInt64NumberArray());
assertArrayEquals(['5300', '5301'], message.repeatedInt64StringArray());
}
function testSerializationSpecialFloatDoubleValues() {
// NaN, Infinity and -Infinity should get serialized as strings.
var message = new proto2.TestAllTypes();
message.setOptionalFloat(Infinity);
message.setOptionalDouble(-Infinity);
message.addRepeatedFloat(Infinity);
message.addRepeatedFloat(-Infinity);
message.addRepeatedFloat(NaN);
message.addRepeatedDouble(Infinity);
message.addRepeatedDouble(-Infinity);
message.addRepeatedDouble(NaN);
var simplified = new goog.proto2.ObjectSerializer().serialize(message);
// Assert that everything serialized properly.
assertEquals('Infinity', simplified[11]);
assertEquals('-Infinity', simplified[12]);
assertEquals('Infinity', simplified[41][0]);
assertEquals('-Infinity', simplified[41][1]);
assertEquals('NaN', simplified[41][2]);
assertEquals('Infinity', simplified[42][0]);
assertEquals('-Infinity', simplified[42][1]);
assertEquals('NaN', simplified[42][2]);
}
function testDeserializationSpecialFloatDoubleValues() {
// NaN, Infinity and -Infinity values should be de-serialized from their
// string representation.
var simplified = {
41: ['Infinity', '-Infinity', 'NaN'],
42: ['Infinity', '-Infinity', 'NaN']
};
var serializer = new goog.proto2.ObjectSerializer();
var message = serializer.deserialize(
proto2.TestAllTypes.getDescriptor(), simplified);
assertNotNull(message);
var floatArray = message.repeatedFloatArray();
assertEquals(Infinity, floatArray[0]);
assertEquals(-Infinity, floatArray[1]);
assertTrue(isNaN(floatArray[2]));
var doubleArray = message.repeatedDoubleArray();
assertEquals(Infinity, doubleArray[0]);
assertEquals(-Infinity, doubleArray[1]);
assertTrue(isNaN(doubleArray[2]));
}
function testDeserializationConversionProhibited() {
// 64-bit types may have been serialized as numbers or strings.
// But 32-bit types must be serialized as numbers.
// Test deserialization fails on 32-bit numbers as strings.
var simplified = {
1: '1000' // optionalInt32
};
var serializer = new goog.proto2.ObjectSerializer();
assertThrows('Should have an assertion failure in deserialization',
function() {
serializer.deserialize(proto2.TestAllTypes.getDescriptor(), simplified);
});
}
function testDefaultValueNumbersOrStrings() {
// 64-bit types may have been serialized as numbers or strings.
// The default values should have the correct type.
var serializer = new goog.proto2.ObjectSerializer();
var message = serializer.deserialize(proto2.TestAllTypes.getDescriptor(), {});
assertNotNull(message);
// Default when using Number is a number, and precision is lost.
var value = message.getOptionalInt64NumberOrDefault();
assertTrue('Expecting a number', typeof value === 'number');
assertEquals(1000000000000000000, value);
assertEquals(1000000000000000001, value);
assertEquals(1000000000000000002, value);
assertEquals('1000000000000000000', String(value)); // Value is rounded!
// When using a String, the value is preserved.
assertEquals('1000000000000000001',
message.getOptionalInt64StringOrDefault());
}
function testBooleanAsNumberFalse() {
// Some libraries, such as GWT, can serialize boolean values as 0/1
var simplified = {
13: 0
};
var serializer = new goog.proto2.ObjectSerializer();
var message = serializer.deserialize(
proto2.TestAllTypes.getDescriptor(), simplified);
assertNotNull(message);
assertFalse(message.getOptionalBool());
}
function testBooleanAsNumberTrue() {
var simplified = {
13: 1
};
var serializer = new goog.proto2.ObjectSerializer();
var message = serializer.deserialize(
proto2.TestAllTypes.getDescriptor(), simplified);
assertNotNull(message);
assertTrue(message.getOptionalBool());
}
@@ -0,0 +1,167 @@
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
//
// Licensed 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.
// All other code copyright its respective owners(s).
/**
* @fileoverview Generated Protocol Buffer code for file
* closure/goog/proto2/package_test.proto.
*/
goog.provide('someprotopackage.TestPackageTypes');
goog.require('goog.proto2.Message');
goog.require('proto2.TestAllTypes');
goog.setTestOnly('package_test.pb');
/**
* Message TestPackageTypes.
* @constructor
* @extends {goog.proto2.Message}
* @final
*/
someprotopackage.TestPackageTypes = function() {
goog.proto2.Message.apply(this);
};
goog.inherits(someprotopackage.TestPackageTypes, goog.proto2.Message);
/**
* Overrides {@link goog.proto2.Message#clone} to specify its exact return type.
* @return {!someprotopackage.TestPackageTypes} The cloned message.
* @override
*/
someprotopackage.TestPackageTypes.prototype.clone;
/**
* Gets the value of the optional_int32 field.
* @return {?number} The value.
*/
someprotopackage.TestPackageTypes.prototype.getOptionalInt32 = function() {
return /** @type {?number} */ (this.get$Value(1));
};
/**
* Gets the value of the optional_int32 field or the default value if not set.
* @return {number} The value.
*/
someprotopackage.TestPackageTypes.prototype.getOptionalInt32OrDefault = function() {
return /** @type {number} */ (this.get$ValueOrDefault(1));
};
/**
* Sets the value of the optional_int32 field.
* @param {number} value The value.
*/
someprotopackage.TestPackageTypes.prototype.setOptionalInt32 = function(value) {
this.set$Value(1, value);
};
/**
* @return {boolean} Whether the optional_int32 field has a value.
*/
someprotopackage.TestPackageTypes.prototype.hasOptionalInt32 = function() {
return this.has$Value(1);
};
/**
* @return {number} The number of values in the optional_int32 field.
*/
someprotopackage.TestPackageTypes.prototype.optionalInt32Count = function() {
return this.count$Values(1);
};
/**
* Clears the values in the optional_int32 field.
*/
someprotopackage.TestPackageTypes.prototype.clearOptionalInt32 = function() {
this.clear$Field(1);
};
/**
* Gets the value of the other_all field.
* @return {proto2.TestAllTypes} The value.
*/
someprotopackage.TestPackageTypes.prototype.getOtherAll = function() {
return /** @type {proto2.TestAllTypes} */ (this.get$Value(2));
};
/**
* Gets the value of the other_all field or the default value if not set.
* @return {!proto2.TestAllTypes} The value.
*/
someprotopackage.TestPackageTypes.prototype.getOtherAllOrDefault = function() {
return /** @type {!proto2.TestAllTypes} */ (this.get$ValueOrDefault(2));
};
/**
* Sets the value of the other_all field.
* @param {!proto2.TestAllTypes} value The value.
*/
someprotopackage.TestPackageTypes.prototype.setOtherAll = function(value) {
this.set$Value(2, value);
};
/**
* @return {boolean} Whether the other_all field has a value.
*/
someprotopackage.TestPackageTypes.prototype.hasOtherAll = function() {
return this.has$Value(2);
};
/**
* @return {number} The number of values in the other_all field.
*/
someprotopackage.TestPackageTypes.prototype.otherAllCount = function() {
return this.count$Values(2);
};
/**
* Clears the values in the other_all field.
*/
someprotopackage.TestPackageTypes.prototype.clearOtherAll = function() {
this.clear$Field(2);
};
goog.proto2.Message.set$Metadata(someprotopackage.TestPackageTypes, {
0: {
name: 'TestPackageTypes',
fullName: 'someprotopackage.TestPackageTypes'
},
1: {
name: 'optional_int32',
fieldType: goog.proto2.Message.FieldType.INT32,
type: Number
},
2: {
name: 'other_all',
fieldType: goog.proto2.Message.FieldType.MESSAGE,
type: proto2.TestAllTypes
}
});
@@ -0,0 +1,199 @@
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
//
// Licensed 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.
/**
* @fileoverview Protocol Buffer 2 Serializer which serializes messages
* into PB-Lite ("JsPbLite") format.
*
* PB-Lite format is an array where each index corresponds to the associated tag
* number. For example, a message like so:
*
* message Foo {
* optional int bar = 1;
* optional int baz = 2;
* optional int bop = 4;
* }
*
* would be represented as such:
*
* [, (bar data), (baz data), (nothing), (bop data)]
*
* Note that since the array index is used to represent the tag number, sparsely
* populated messages with tag numbers that are not continuous (and/or are very
* large) will have many (empty) spots and thus, are inefficient.
*
*
*/
goog.provide('goog.proto2.PbLiteSerializer');
goog.require('goog.asserts');
goog.require('goog.proto2.FieldDescriptor');
goog.require('goog.proto2.LazyDeserializer');
goog.require('goog.proto2.Serializer');
/**
* PB-Lite serializer.
*
* @constructor
* @extends {goog.proto2.LazyDeserializer}
*/
goog.proto2.PbLiteSerializer = function() {};
goog.inherits(goog.proto2.PbLiteSerializer, goog.proto2.LazyDeserializer);
/**
* If true, fields will be serialized with 0-indexed tags (i.e., the proto
* field with tag id 1 will have index 0 in the array).
* @type {boolean}
* @private
*/
goog.proto2.PbLiteSerializer.prototype.zeroIndexing_ = false;
/**
* By default, the proto tag with id 1 will have index 1 in the serialized
* array.
*
* If the serializer is set to use zero-indexing, the tag with id 1 will have
* index 0.
*
* @param {boolean} zeroIndexing Whether this serializer should deal with
* 0-indexed protos.
*/
goog.proto2.PbLiteSerializer.prototype.setZeroIndexed = function(zeroIndexing) {
this.zeroIndexing_ = zeroIndexing;
};
/**
* Serializes a message to a PB-Lite object.
*
* @param {goog.proto2.Message} message The message to be serialized.
* @return {!Array<?>} The serialized form of the message.
* @override
*/
goog.proto2.PbLiteSerializer.prototype.serialize = function(message) {
var descriptor = message.getDescriptor();
var fields = descriptor.getFields();
var serialized = [];
var zeroIndexing = this.zeroIndexing_;
// Add the known fields.
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
if (!message.has(field)) {
continue;
}
var tag = field.getTag();
var index = zeroIndexing ? tag - 1 : tag;
if (field.isRepeated()) {
serialized[index] = [];
for (var j = 0; j < message.countOf(field); j++) {
serialized[index][j] =
this.getSerializedValue(field, message.get(field, j));
}
} else {
serialized[index] = this.getSerializedValue(field, message.get(field));
}
}
// Add any unknown fields.
message.forEachUnknown(function(tag, value) {
var index = zeroIndexing ? tag - 1 : tag;
serialized[index] = value;
});
return serialized;
};
/** @override */
goog.proto2.PbLiteSerializer.prototype.deserializeField =
function(message, field, value) {
if (value == null) {
// Since value double-equals null, it may be either null or undefined.
// Ensure we return the same one, since they have different meanings.
// TODO(user): If the field is repeated, this method should probably
// return [] instead of null.
return value;
}
if (field.isRepeated()) {
var data = [];
goog.asserts.assert(goog.isArray(value), 'Value must be array: %s', value);
for (var i = 0; i < value.length; i++) {
data[i] = this.getDeserializedValue(field, value[i]);
}
return data;
} else {
return this.getDeserializedValue(field, value);
}
};
/** @override */
goog.proto2.PbLiteSerializer.prototype.getSerializedValue =
function(field, value) {
if (field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.BOOL) {
// Booleans are serialized in numeric form.
return value ? 1 : 0;
}
return goog.proto2.Serializer.prototype.getSerializedValue.apply(this,
arguments);
};
/** @override */
goog.proto2.PbLiteSerializer.prototype.getDeserializedValue =
function(field, value) {
if (field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.BOOL) {
goog.asserts.assert(goog.isNumber(value) || goog.isBoolean(value),
'Value is expected to be a number or boolean');
return !!value;
}
return goog.proto2.Serializer.prototype.getDeserializedValue.apply(this,
arguments);
};
/** @override */
goog.proto2.PbLiteSerializer.prototype.deserialize =
function(descriptor, data) {
var toConvert = data;
if (this.zeroIndexing_) {
// Make the data align with tag-IDs (1-indexed) by shifting everything
// up one.
toConvert = [];
for (var key in data) {
toConvert[parseInt(key, 10) + 1] = data[key];
}
}
return goog.proto2.PbLiteSerializer.base(
this, 'deserialize', descriptor, toConvert);
};
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<!--
Copyright 2008 The Closure Library Authors. All Rights Reserved.
Use of this source code is governed by the Apache License, Version 2.0.
See the COPYING file for details.
-->
<!--
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>
Closure Unit Tests - goog.proto2 - pbliteserializer.js
</title>
<script src="../base.js">
</script>
<script>
goog.require('goog.proto2.PbLiteSerializerTest');
</script>
</head>
<body>
</body>
</html>
@@ -0,0 +1,499 @@
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
//
// Licensed 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.
goog.provide('goog.proto2.PbLiteSerializerTest');
goog.setTestOnly('goog.proto2.PbLiteSerializerTest');
goog.require('goog.proto2.PbLiteSerializer');
goog.require('goog.testing.jsunit');
goog.require('proto2.TestAllTypes');
function testSerializationAndDeserialization() {
var message = createPopulatedMessage();
// Serialize.
var serializer = new goog.proto2.PbLiteSerializer();
var pblite = serializer.serialize(message);
assertTrue(goog.isArray(pblite));
// Assert that everything serialized properly.
assertEquals(101, pblite[1]);
assertEquals('102', pblite[2]);
assertEquals(103, pblite[3]);
assertEquals('104', pblite[4]);
assertEquals(105, pblite[5]);
assertEquals('106', pblite[6]);
assertEquals(107, pblite[7]);
assertEquals('108', pblite[8]);
assertEquals(109, pblite[9]);
assertEquals('110', pblite[10]);
assertEquals(111.5, pblite[11]);
assertEquals(112.5, pblite[12]);
assertEquals(1, pblite[13]); // true is serialized as 1
assertEquals('test', pblite[14]);
assertEquals('abcd', pblite[15]);
assertEquals(111, pblite[16][17]);
assertEquals(112, pblite[18][1]);
assertTrue(pblite[19] === undefined);
assertTrue(pblite[20] === undefined);
assertEquals(proto2.TestAllTypes.NestedEnum.FOO, pblite[21]);
assertEquals(201, pblite[31][0]);
assertEquals(202, pblite[31][1]);
assertEquals('foo', pblite[44][0]);
assertEquals('bar', pblite[44][1]);
var serializer = new goog.proto2.PbLiteSerializer();
// Deserialize.
var messageCopy =
serializer.deserialize(proto2.TestAllTypes.getDescriptor(), pblite);
assertNotEquals(messageCopy, message);
assertDeserializationMatches(messageCopy);
}
function testZeroBasedSerializationAndDeserialization() {
var message = createPopulatedMessage();
// Serialize.
var serializer = new goog.proto2.PbLiteSerializer();
serializer.setZeroIndexed(true);
var pblite = serializer.serialize(message);
assertTrue(goog.isArray(pblite));
// Assert that everything serialized properly.
assertEquals(101, pblite[0]);
assertEquals('102', pblite[1]);
assertEquals(103, pblite[2]);
assertEquals('104', pblite[3]);
assertEquals(105, pblite[4]);
assertEquals('106', pblite[5]);
assertEquals(107, pblite[6]);
assertEquals('108', pblite[7]);
assertEquals(109, pblite[8]);
assertEquals('110', pblite[9]);
assertEquals(111.5, pblite[10]);
assertEquals(112.5, pblite[11]);
assertEquals(1, pblite[12]); // true is serialized as 1
assertEquals('test', pblite[13]);
assertEquals('abcd', pblite[14]);
assertEquals(111, pblite[15][16]);
assertEquals(112, pblite[17][0]);
assertTrue(pblite[18] === undefined);
assertTrue(pblite[19] === undefined);
assertEquals(proto2.TestAllTypes.NestedEnum.FOO, pblite[20]);
assertEquals(201, pblite[30][0]);
assertEquals(202, pblite[30][1]);
assertEquals('foo', pblite[43][0]);
assertEquals('bar', pblite[43][1]);
// Deserialize.
var messageCopy =
serializer.deserialize(proto2.TestAllTypes.getDescriptor(), pblite);
assertNotEquals(messageCopy, message);
assertEquals(message.getOptionalInt32(), messageCopy.getOptionalInt32());
assertDeserializationMatches(messageCopy);
}
function createPopulatedMessage() {
var message = new proto2.TestAllTypes();
// Set the fields.
// Singular.
message.setOptionalInt32(101);
message.setOptionalInt64('102');
message.setOptionalUint32(103);
message.setOptionalUint64('104');
message.setOptionalSint32(105);
message.setOptionalSint64('106');
message.setOptionalFixed32(107);
message.setOptionalFixed64('108');
message.setOptionalSfixed32(109);
message.setOptionalSfixed64('110');
message.setOptionalFloat(111.5);
message.setOptionalDouble(112.5);
message.setOptionalBool(true);
message.setOptionalString('test');
message.setOptionalBytes('abcd');
var group = new proto2.TestAllTypes.OptionalGroup();
group.setA(111);
message.setOptionalgroup(group);
var nestedMessage = new proto2.TestAllTypes.NestedMessage();
nestedMessage.setB(112);
message.setOptionalNestedMessage(nestedMessage);
message.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
// Repeated.
message.addRepeatedInt32(201);
message.addRepeatedInt32(202);
// Skip a few repeated fields so we can test how null array values are
// handled.
message.addRepeatedString('foo');
message.addRepeatedString('bar');
return message;
}
function testDeserializationFromExternalSource() {
// Test deserialization where the JSON array is initialized from something
// outside the Closure proto2 library, such as the JsPbLite library, or
// manually as in this test.
var pblite = [
, // 0
101, // 1
'102', // 2
103, // 3
'104', // 4
105, // 5
'106', // 6
107, // 7
'108', // 8
109, // 9
'110', // 10
111.5, // 11
112.5, // 12
1, // 13
'test', // 14
'abcd', // 15
[,,,,,,,,,,,,,,,,, 111], // 16, note the 17 commas so value is index 17
, // 17
[, 112], // 18
,, // 19-20
proto2.TestAllTypes.NestedEnum.FOO, // 21
,,,,,,,,, // 22-30
[201, 202], // 31
,,,,,,,,,,,, // 32-43
['foo', 'bar'], // 44
,,,, // 45-49
];
// Deserialize.
var serializer = new goog.proto2.PbLiteSerializer();
var messageCopy =
serializer.deserialize(proto2.TestAllTypes.getDescriptor(), pblite);
assertDeserializationMatches(messageCopy);
// http://b/issue?id=2928075
assertFalse(messageCopy.hasRepeatedInt64());
assertEquals(0, messageCopy.repeatedInt64Count());
messageCopy.repeatedInt64Array();
assertFalse(messageCopy.hasRepeatedInt64());
assertEquals(0, messageCopy.repeatedInt64Count());
// Access a nested message to ensure it is deserialized.
assertNotNull(messageCopy.getOptionalNestedMessage());
// Verify that the pblite array itself has not been replaced by the
// deserialization.
assertEquals('array', goog.typeOf(pblite[16]));
// Update some fields and verify that the changes work with the lazy
// deserializer.
messageCopy.setOptionalBool(true);
assertTrue(messageCopy.getOptionalBool());
messageCopy.setOptionalBool(false);
assertFalse(messageCopy.getOptionalBool());
messageCopy.setOptionalInt32(1234);
assertEquals(1234, messageCopy.getOptionalInt32());
}
function testModifyLazyDeserializedMessage() {
var pblite = [
, // 0
101, // 1
'102', // 2
103, // 3
'104', // 4
105, // 5
'106', // 6
107, // 7
'108', // 8
109, // 9
'110', // 10
111.5, // 11
112.5, // 12
1, // 13
'test', // 14
'abcd', // 15
[,,,,,,,,,,,,,,,,, 111], // 16, note the 17 commas so value is index 17
, // 17
[, 112], // 18
,, // 19-20
proto2.TestAllTypes.NestedEnum.FOO, // 21
,,,,,,,,, // 22-30
[201, 202], // 31
,,,,,,,,,,,, // 32-43
['foo', 'bar'], // 44
,,,, // 45-49
];
// Deserialize.
var serializer = new goog.proto2.PbLiteSerializer();
var message =
serializer.deserialize(proto2.TestAllTypes.getDescriptor(), pblite);
// Conduct some operations, ensuring that they all work as expected, even with
// the lazily deserialized data.
assertEquals(101, message.getOptionalInt32());
message.setOptionalInt32(401);
assertEquals(401, message.getOptionalInt32());
assertEquals(2, message.repeatedInt32Count());
assertEquals(201, message.getRepeatedInt32(0));
assertEquals(202, message.getRepeatedInt32(1));
message.clearRepeatedInt32();
assertEquals(0, message.repeatedInt32Count());
message.addRepeatedInt32(101);
assertEquals(1, message.repeatedInt32Count());
assertEquals(101, message.getRepeatedInt32(0));
message.setUnknown(12345, 601);
message.forEachUnknown(function(tag, value) {
assertEquals(12345, tag);
assertEquals(601, value);
});
// Create a copy of the message.
var messageCopy = new proto2.TestAllTypes();
messageCopy.copyFrom(message);
assertEquals(1, messageCopy.repeatedInt32Count());
assertEquals(101, messageCopy.getRepeatedInt32(0));
}
function testModifyLazyDeserializedMessageByAddingMessage() {
var pblite = [
, // 0
101, // 1
'102', // 2
103, // 3
'104', // 4
105, // 5
'106', // 6
107, // 7
'108', // 8
109, // 9
'110', // 10
111.5, // 11
112.5, // 12
1, // 13
'test', // 14
'abcd', // 15
[,,,,,,,,,,,,,,,,, 111], // 16, note the 17 commas so value is index 17
, // 17
[, 112], // 18
,, // 19-20
proto2.TestAllTypes.NestedEnum.FOO, // 21
,,,,,,,,, // 22-30
[201, 202], // 31
,,,,,,,,,,,, // 32-43
['foo', 'bar'], // 44
,,,, // 45-49
];
// Deserialize.
var serializer = new goog.proto2.PbLiteSerializer();
var message =
serializer.deserialize(proto2.TestAllTypes.getDescriptor(), pblite);
// Add a new nested message.
var nested1 = new proto2.TestAllTypes.NestedMessage();
nested1.setB(1234);
var nested2 = new proto2.TestAllTypes.NestedMessage();
nested2.setB(4567);
message.addRepeatedNestedMessage(nested1);
// Check the new nested message.
assertEquals(1, message.repeatedNestedMessageArray().length);
assertTrue(message.repeatedNestedMessageArray()[0].equals(nested1));
// Add another nested message.
message.addRepeatedNestedMessage(nested2);
// Check both nested messages.
assertEquals(2, message.repeatedNestedMessageArray().length);
assertTrue(message.repeatedNestedMessageArray()[0].equals(nested1));
assertTrue(message.repeatedNestedMessageArray()[1].equals(nested2));
}
function assertDeserializationMatches(messageCopy) {
assertNotNull(messageCopy);
assertTrue(messageCopy.hasOptionalInt32());
assertTrue(messageCopy.hasOptionalInt64());
assertTrue(messageCopy.hasOptionalUint32());
assertTrue(messageCopy.hasOptionalUint64());
assertTrue(messageCopy.hasOptionalSint32());
assertTrue(messageCopy.hasOptionalSint64());
assertTrue(messageCopy.hasOptionalFixed32());
assertTrue(messageCopy.hasOptionalFixed64());
assertTrue(messageCopy.hasOptionalSfixed32());
assertTrue(messageCopy.hasOptionalSfixed64());
assertTrue(messageCopy.hasOptionalFloat());
assertTrue(messageCopy.hasOptionalDouble());
assertTrue(messageCopy.hasOptionalBool());
assertTrue(messageCopy.hasOptionalString());
assertTrue(messageCopy.hasOptionalBytes());
assertTrue(messageCopy.hasOptionalgroup());
assertTrue(messageCopy.hasOptionalNestedMessage());
assertTrue(messageCopy.hasOptionalNestedEnum());
assertTrue(messageCopy.hasRepeatedInt32());
assertFalse(messageCopy.hasRepeatedInt64());
assertFalse(messageCopy.hasRepeatedUint32());
assertFalse(messageCopy.hasRepeatedUint64());
assertFalse(messageCopy.hasRepeatedSint32());
assertFalse(messageCopy.hasRepeatedSint64());
assertFalse(messageCopy.hasRepeatedFixed32());
assertFalse(messageCopy.hasRepeatedFixed64());
assertFalse(messageCopy.hasRepeatedSfixed32());
assertFalse(messageCopy.hasRepeatedSfixed64());
assertFalse(messageCopy.hasRepeatedFloat());
assertFalse(messageCopy.hasRepeatedDouble());
assertFalse(messageCopy.hasRepeatedBool());
assertTrue(messageCopy.hasRepeatedString());
assertFalse(messageCopy.hasRepeatedBytes());
assertFalse(messageCopy.hasRepeatedgroup());
assertFalse(messageCopy.hasRepeatedNestedMessage());
assertFalse(messageCopy.hasRepeatedNestedEnum());
assertEquals(1, messageCopy.optionalInt32Count());
assertEquals(1, messageCopy.optionalInt64Count());
assertEquals(1, messageCopy.optionalUint32Count());
assertEquals(1, messageCopy.optionalUint64Count());
assertEquals(1, messageCopy.optionalSint32Count());
assertEquals(1, messageCopy.optionalSint64Count());
assertEquals(1, messageCopy.optionalFixed32Count());
assertEquals(1, messageCopy.optionalFixed64Count());
assertEquals(1, messageCopy.optionalSfixed32Count());
assertEquals(1, messageCopy.optionalSfixed64Count());
assertEquals(1, messageCopy.optionalFloatCount());
assertEquals(1, messageCopy.optionalDoubleCount());
assertEquals(1, messageCopy.optionalBoolCount());
assertEquals(1, messageCopy.optionalStringCount());
assertEquals(1, messageCopy.optionalBytesCount());
assertEquals(1, messageCopy.optionalgroupCount());
assertEquals(1, messageCopy.optionalNestedMessageCount());
assertEquals(1, messageCopy.optionalNestedEnumCount());
assertEquals(2, messageCopy.repeatedInt32Count());
assertEquals(0, messageCopy.repeatedInt64Count());
assertEquals(0, messageCopy.repeatedUint32Count());
assertEquals(0, messageCopy.repeatedUint64Count());
assertEquals(0, messageCopy.repeatedSint32Count());
assertEquals(0, messageCopy.repeatedSint64Count());
assertEquals(0, messageCopy.repeatedFixed32Count());
assertEquals(0, messageCopy.repeatedFixed64Count());
assertEquals(0, messageCopy.repeatedSfixed32Count());
assertEquals(0, messageCopy.repeatedSfixed64Count());
assertEquals(0, messageCopy.repeatedFloatCount());
assertEquals(0, messageCopy.repeatedDoubleCount());
assertEquals(0, messageCopy.repeatedBoolCount());
assertEquals(2, messageCopy.repeatedStringCount());
assertEquals(0, messageCopy.repeatedBytesCount());
assertEquals(0, messageCopy.repeatedgroupCount());
assertEquals(0, messageCopy.repeatedNestedMessageCount());
assertEquals(0, messageCopy.repeatedNestedEnumCount());
assertEquals(101, messageCopy.getOptionalInt32());
assertEquals('102', messageCopy.getOptionalInt64());
assertEquals(103, messageCopy.getOptionalUint32());
assertEquals('104', messageCopy.getOptionalUint64());
assertEquals(105, messageCopy.getOptionalSint32());
assertEquals('106', messageCopy.getOptionalSint64());
assertEquals(107, messageCopy.getOptionalFixed32());
assertEquals('108', messageCopy.getOptionalFixed64());
assertEquals(109, messageCopy.getOptionalSfixed32());
assertEquals('110', messageCopy.getOptionalSfixed64());
assertEquals(111.5, messageCopy.getOptionalFloat());
assertEquals(112.5, messageCopy.getOptionalDouble());
assertEquals(true, messageCopy.getOptionalBool());
assertEquals('test', messageCopy.getOptionalString());
assertEquals('abcd', messageCopy.getOptionalBytes());
assertEquals(111, messageCopy.getOptionalgroup().getA());
assertEquals(112, messageCopy.getOptionalNestedMessage().getB());
assertEquals(proto2.TestAllTypes.NestedEnum.FOO,
messageCopy.getOptionalNestedEnum());
assertEquals(201, messageCopy.getRepeatedInt32(0));
assertEquals(202, messageCopy.getRepeatedInt32(1));
}
function testMergeFromLazyTarget() {
var serializer = new goog.proto2.PbLiteSerializer();
var source = new proto2.TestAllTypes();
var nested = new proto2.TestAllTypes.NestedMessage();
nested.setB(66);
source.setOptionalNestedMessage(nested);
source.setOptionalInt32(32);
source.setOptionalString('foo');
source.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
source.addRepeatedInt32(2);
var target = new proto2.TestAllTypes();
nested = new proto2.TestAllTypes.NestedMessage();
nested.setC(77);
target.setOptionalNestedMessage(nested);
target.setOptionalInt64('64');
target.setOptionalString('bar');
target.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.BAR);
target.addRepeatedInt32(1);
var pbliteTarget = serializer.serialize(target);
var lazyTarget =
serializer.deserialize(proto2.TestAllTypes.getDescriptor(), pbliteTarget);
var expected = new proto2.TestAllTypes();
nested = new proto2.TestAllTypes.NestedMessage();
nested.setB(66);
nested.setC(77);
expected.setOptionalNestedMessage(nested);
expected.setOptionalInt32(32);
expected.setOptionalInt64('64');
expected.setOptionalString('foo');
expected.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
expected.addRepeatedInt32(1);
expected.addRepeatedInt32(2);
lazyTarget.mergeFrom(source);
assertTrue('expected and lazyTarget are equal after mergeFrom',
lazyTarget.equals(expected));
}
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<!--
Copyright 2008 The Closure Library Authors. All Rights Reserved.
Use of this source code is governed by the Apache License, Version 2.0.
See the COPYING file for details.
-->
<!--
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>
Closure Unit Tests - goog.proto2 - Message Tests
</title>
<script src="../base.js">
</script>
<script>
goog.require('goog.proto2.messageTest');
</script>
</head>
<body>
</body>
</html>
@@ -0,0 +1,755 @@
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
//
// Licensed 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.
goog.provide('goog.proto2.messageTest');
goog.setTestOnly('goog.proto2.messageTest');
goog.require('goog.proto2.FieldDescriptor');
goog.require('goog.testing.jsunit');
goog.require('proto2.TestAllTypes');
goog.require('someprotopackage.TestPackageTypes');
function testPackage() {
var message = new someprotopackage.TestPackageTypes();
message.setOptionalInt32(45);
message.setOtherAll(new proto2.TestAllTypes());
}
function testFields() {
var message = new proto2.TestAllTypes();
// Ensure that the fields are not set.
assertFalse(message.hasOptionalInt32());
assertFalse(message.hasOptionalInt64());
assertFalse(message.hasOptionalUint32());
assertFalse(message.hasOptionalUint64());
assertFalse(message.hasOptionalSint32());
assertFalse(message.hasOptionalSint64());
assertFalse(message.hasOptionalFixed32());
assertFalse(message.hasOptionalFixed64());
assertFalse(message.hasOptionalSfixed32());
assertFalse(message.hasOptionalSfixed64());
assertFalse(message.hasOptionalFloat());
assertFalse(message.hasOptionalDouble());
assertFalse(message.hasOptionalBool());
assertFalse(message.hasOptionalString());
assertFalse(message.hasOptionalBytes());
assertFalse(message.hasOptionalgroup());
assertFalse(message.hasOptionalNestedMessage());
assertFalse(message.hasOptionalNestedEnum());
// Check non-set values.
assertNull(message.getOptionalInt32());
assertNull(message.getOptionalInt64());
assertNull(message.getOptionalFloat());
assertNull(message.getOptionalString());
assertNull(message.getOptionalBytes());
assertNull(message.getOptionalNestedMessage());
assertNull(message.getOptionalNestedEnum());
// Check default values.
assertEquals(0, message.getOptionalInt32OrDefault());
assertEquals('1', message.getOptionalInt64OrDefault());
assertEquals(1.5, message.getOptionalFloatOrDefault());
assertEquals('', message.getOptionalStringOrDefault());
assertEquals('moo', message.getOptionalBytesOrDefault());
// Set the fields.
message.setOptionalInt32(101);
message.setOptionalInt64('102');
message.setOptionalUint32(103);
message.setOptionalUint64('104');
message.setOptionalSint32(105);
message.setOptionalSint64('106');
message.setOptionalFixed32(107);
message.setOptionalFixed64('108');
message.setOptionalSfixed32(109);
message.setOptionalSfixed64('110');
message.setOptionalFloat(111.5);
message.setOptionalDouble(112.5);
message.setOptionalBool(true);
message.setOptionalString('test');
message.setOptionalBytes('abcd');
var group = new proto2.TestAllTypes.OptionalGroup();
group.setA(111);
message.setOptionalgroup(group);
var nestedMessage = new proto2.TestAllTypes.NestedMessage();
nestedMessage.setB(112);
message.setOptionalNestedMessage(nestedMessage);
message.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
// Ensure that the fields are set.
assertTrue(message.hasOptionalInt32());
assertTrue(message.hasOptionalInt64());
assertTrue(message.hasOptionalUint32());
assertTrue(message.hasOptionalUint64());
assertTrue(message.hasOptionalSint32());
assertTrue(message.hasOptionalSint64());
assertTrue(message.hasOptionalFixed32());
assertTrue(message.hasOptionalFixed64());
assertTrue(message.hasOptionalSfixed32());
assertTrue(message.hasOptionalSfixed64());
assertTrue(message.hasOptionalFloat());
assertTrue(message.hasOptionalDouble());
assertTrue(message.hasOptionalBool());
assertTrue(message.hasOptionalString());
assertTrue(message.hasOptionalBytes());
assertTrue(message.hasOptionalgroup());
assertTrue(message.hasOptionalNestedMessage());
assertTrue(message.hasOptionalNestedEnum());
// Ensure that there is a count of 1 for each of the fields.
assertEquals(1, message.optionalInt32Count());
assertEquals(1, message.optionalInt64Count());
assertEquals(1, message.optionalUint32Count());
assertEquals(1, message.optionalUint64Count());
assertEquals(1, message.optionalSint32Count());
assertEquals(1, message.optionalSint64Count());
assertEquals(1, message.optionalFixed32Count());
assertEquals(1, message.optionalFixed64Count());
assertEquals(1, message.optionalSfixed32Count());
assertEquals(1, message.optionalSfixed64Count());
assertEquals(1, message.optionalFloatCount());
assertEquals(1, message.optionalDoubleCount());
assertEquals(1, message.optionalBoolCount());
assertEquals(1, message.optionalStringCount());
assertEquals(1, message.optionalBytesCount());
assertEquals(1, message.optionalgroupCount());
assertEquals(1, message.optionalNestedMessageCount());
assertEquals(1, message.optionalNestedEnumCount());
// Ensure that the fields have the values expected.
assertEquals(101, message.getOptionalInt32());
assertEquals('102', message.getOptionalInt64());
assertEquals(103, message.getOptionalUint32());
assertEquals('104', message.getOptionalUint64());
assertEquals(105, message.getOptionalSint32());
assertEquals('106', message.getOptionalSint64());
assertEquals(107, message.getOptionalFixed32());
assertEquals('108', message.getOptionalFixed64());
assertEquals(109, message.getOptionalSfixed32());
assertEquals('110', message.getOptionalSfixed64());
assertEquals(111.5, message.getOptionalFloat());
assertEquals(112.5, message.getOptionalDouble());
assertEquals(true, message.getOptionalBool());
assertEquals('test', message.getOptionalString());
assertEquals('abcd', message.getOptionalBytes());
assertEquals(group, message.getOptionalgroup());
assertEquals(nestedMessage, message.getOptionalNestedMessage());
assertEquals(proto2.TestAllTypes.NestedEnum.FOO,
message.getOptionalNestedEnum());
}
function testRepeated() {
var message = new proto2.TestAllTypes();
// Ensure that the fields are not set.
assertFalse(message.hasRepeatedInt32());
assertFalse(message.hasRepeatedInt64());
assertFalse(message.hasRepeatedUint32());
assertFalse(message.hasRepeatedUint64());
assertFalse(message.hasRepeatedSint32());
assertFalse(message.hasRepeatedSint64());
assertFalse(message.hasRepeatedFixed32());
assertFalse(message.hasRepeatedFixed64());
assertFalse(message.hasRepeatedSfixed32());
assertFalse(message.hasRepeatedSfixed64());
assertFalse(message.hasRepeatedFloat());
assertFalse(message.hasRepeatedDouble());
assertFalse(message.hasRepeatedBool());
assertFalse(message.hasRepeatedString());
assertFalse(message.hasRepeatedBytes());
assertFalse(message.hasRepeatedgroup());
assertFalse(message.hasRepeatedNestedMessage());
assertFalse(message.hasRepeatedNestedEnum());
// Expect the arrays to be empty.
assertEquals(0, message.repeatedInt32Array().length);
assertEquals(0, message.repeatedInt64Array().length);
assertEquals(0, message.repeatedUint32Array().length);
assertEquals(0, message.repeatedUint64Array().length);
assertEquals(0, message.repeatedSint32Array().length);
assertEquals(0, message.repeatedSint64Array().length);
assertEquals(0, message.repeatedFixed32Array().length);
assertEquals(0, message.repeatedFixed64Array().length);
assertEquals(0, message.repeatedSfixed32Array().length);
assertEquals(0, message.repeatedSfixed64Array().length);
assertEquals(0, message.repeatedFloatArray().length);
assertEquals(0, message.repeatedDoubleArray().length);
assertEquals(0, message.repeatedBoolArray().length);
assertEquals(0, message.repeatedStringArray().length);
assertEquals(0, message.repeatedBytesArray().length);
assertEquals(0, message.repeatedgroupArray().length);
assertEquals(0, message.repeatedNestedMessageArray().length);
assertEquals(0, message.repeatedNestedEnumArray().length);
// Set the fields.
message.addRepeatedInt32(101);
message.addRepeatedInt64('102');
message.addRepeatedUint32(103);
message.addRepeatedUint64('104');
message.addRepeatedSint32(105);
message.addRepeatedSint64('106');
message.addRepeatedFixed32(107);
message.addRepeatedFixed64('108');
message.addRepeatedSfixed32(109);
message.addRepeatedSfixed64('110');
message.addRepeatedFloat(111.5);
message.addRepeatedDouble(112.5);
message.addRepeatedBool(true);
message.addRepeatedString('test');
message.addRepeatedBytes('abcd');
message.addRepeatedInt32(201);
message.addRepeatedInt64('202');
message.addRepeatedUint32(203);
message.addRepeatedUint64('204');
message.addRepeatedSint32(205);
message.addRepeatedSint64('206');
message.addRepeatedFixed32(207);
message.addRepeatedFixed64('208');
message.addRepeatedSfixed32(209);
message.addRepeatedSfixed64('210');
message.addRepeatedFloat(211.5);
message.addRepeatedDouble(212.5);
message.addRepeatedBool(true);
message.addRepeatedString('test#2');
message.addRepeatedBytes('efgh');
var group1 = new proto2.TestAllTypes.RepeatedGroup();
group1.addA(111);
message.addRepeatedgroup(group1);
var group2 = new proto2.TestAllTypes.RepeatedGroup();
group2.addA(211);
message.addRepeatedgroup(group2);
var nestedMessage1 = new proto2.TestAllTypes.NestedMessage();
nestedMessage1.setB(112);
message.addRepeatedNestedMessage(nestedMessage1);
var nestedMessage2 = new proto2.TestAllTypes.NestedMessage();
nestedMessage2.setB(212);
message.addRepeatedNestedMessage(nestedMessage2);
message.addRepeatedNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
message.addRepeatedNestedEnum(proto2.TestAllTypes.NestedEnum.BAR);
// Ensure that the fields are set.
assertTrue(message.hasRepeatedInt32());
assertTrue(message.hasRepeatedInt64());
assertTrue(message.hasRepeatedUint32());
assertTrue(message.hasRepeatedUint64());
assertTrue(message.hasRepeatedSint32());
assertTrue(message.hasRepeatedSint64());
assertTrue(message.hasRepeatedFixed32());
assertTrue(message.hasRepeatedFixed64());
assertTrue(message.hasRepeatedSfixed32());
assertTrue(message.hasRepeatedSfixed64());
assertTrue(message.hasRepeatedFloat());
assertTrue(message.hasRepeatedDouble());
assertTrue(message.hasRepeatedBool());
assertTrue(message.hasRepeatedString());
assertTrue(message.hasRepeatedBytes());
assertTrue(message.hasRepeatedgroup());
assertTrue(message.hasRepeatedNestedMessage());
assertTrue(message.hasRepeatedNestedEnum());
// Ensure that there is a count of 2 for each of the fields.
assertEquals(2, message.repeatedInt32Count());
assertEquals(2, message.repeatedInt64Count());
assertEquals(2, message.repeatedUint32Count());
assertEquals(2, message.repeatedUint64Count());
assertEquals(2, message.repeatedSint32Count());
assertEquals(2, message.repeatedSint64Count());
assertEquals(2, message.repeatedFixed32Count());
assertEquals(2, message.repeatedFixed64Count());
assertEquals(2, message.repeatedSfixed32Count());
assertEquals(2, message.repeatedSfixed64Count());
assertEquals(2, message.repeatedFloatCount());
assertEquals(2, message.repeatedDoubleCount());
assertEquals(2, message.repeatedBoolCount());
assertEquals(2, message.repeatedStringCount());
assertEquals(2, message.repeatedBytesCount());
assertEquals(2, message.repeatedgroupCount());
assertEquals(2, message.repeatedNestedMessageCount());
assertEquals(2, message.repeatedNestedEnumCount());
// Ensure that the fields have the values expected.
assertEquals(101, message.getRepeatedInt32(0));
assertEquals('102', message.getRepeatedInt64(0));
assertEquals(103, message.getRepeatedUint32(0));
assertEquals('104', message.getRepeatedUint64(0));
assertEquals(105, message.getRepeatedSint32(0));
assertEquals('106', message.getRepeatedSint64(0));
assertEquals(107, message.getRepeatedFixed32(0));
assertEquals('108', message.getRepeatedFixed64(0));
assertEquals(109, message.getRepeatedSfixed32(0));
assertEquals('110', message.getRepeatedSfixed64(0));
assertEquals(111.5, message.getRepeatedFloat(0));
assertEquals(112.5, message.getRepeatedDouble(0));
assertEquals(true, message.getRepeatedBool(0));
assertEquals('test', message.getRepeatedString(0));
assertEquals('abcd', message.getRepeatedBytes(0));
assertEquals(group1, message.getRepeatedgroup(0));
assertEquals(nestedMessage1, message.getRepeatedNestedMessage(0));
assertEquals(proto2.TestAllTypes.NestedEnum.FOO,
message.getRepeatedNestedEnum(0));
assertEquals(201, message.getRepeatedInt32(1));
assertEquals('202', message.getRepeatedInt64(1));
assertEquals(203, message.getRepeatedUint32(1));
assertEquals('204', message.getRepeatedUint64(1));
assertEquals(205, message.getRepeatedSint32(1));
assertEquals('206', message.getRepeatedSint64(1));
assertEquals(207, message.getRepeatedFixed32(1));
assertEquals('208', message.getRepeatedFixed64(1));
assertEquals(209, message.getRepeatedSfixed32(1));
assertEquals('210', message.getRepeatedSfixed64(1));
assertEquals(211.5, message.getRepeatedFloat(1));
assertEquals(212.5, message.getRepeatedDouble(1));
assertEquals(true, message.getRepeatedBool(1));
assertEquals('test#2', message.getRepeatedString(1));
assertEquals('efgh', message.getRepeatedBytes(1));
assertEquals(group2, message.getRepeatedgroup(1));
assertEquals(nestedMessage2, message.getRepeatedNestedMessage(1));
assertEquals(proto2.TestAllTypes.NestedEnum.BAR,
message.getRepeatedNestedEnum(1));
// Check the array lengths.
assertEquals(2, message.repeatedInt32Array().length);
assertEquals(2, message.repeatedInt64Array().length);
assertEquals(2, message.repeatedUint32Array().length);
assertEquals(2, message.repeatedUint64Array().length);
assertEquals(2, message.repeatedSint32Array().length);
assertEquals(2, message.repeatedSint64Array().length);
assertEquals(2, message.repeatedFixed32Array().length);
assertEquals(2, message.repeatedFixed64Array().length);
assertEquals(2, message.repeatedSfixed32Array().length);
assertEquals(2, message.repeatedSfixed64Array().length);
assertEquals(2, message.repeatedFloatArray().length);
assertEquals(2, message.repeatedDoubleArray().length);
assertEquals(2, message.repeatedBoolArray().length);
assertEquals(2, message.repeatedStringArray().length);
assertEquals(2, message.repeatedBytesArray().length);
assertEquals(2, message.repeatedgroupArray().length);
assertEquals(2, message.repeatedNestedMessageArray().length);
assertEquals(2, message.repeatedNestedEnumArray().length);
// Check the array values.
assertEquals(message.getRepeatedInt32(0), message.repeatedInt32Array()[0]);
assertEquals(message.getRepeatedInt64(0), message.repeatedInt64Array()[0]);
assertEquals(message.getRepeatedUint32(0), message.repeatedUint32Array()[0]);
assertEquals(message.getRepeatedUint64(0), message.repeatedUint64Array()[0]);
assertEquals(message.getRepeatedSint32(0), message.repeatedSint32Array()[0]);
assertEquals(message.getRepeatedSint64(0), message.repeatedSint64Array()[0]);
assertEquals(message.getRepeatedFixed32(0),
message.repeatedFixed32Array()[0]);
assertEquals(message.getRepeatedFixed64(0),
message.repeatedFixed64Array()[0]);
assertEquals(message.getRepeatedSfixed32(0),
message.repeatedSfixed32Array()[0]);
assertEquals(message.getRepeatedSfixed64(0),
message.repeatedSfixed64Array()[0]);
assertEquals(message.getRepeatedFloat(0), message.repeatedFloatArray()[0]);
assertEquals(message.getRepeatedDouble(0), message.repeatedDoubleArray()[0]);
assertEquals(message.getRepeatedBool(0), message.repeatedBoolArray()[0]);
assertEquals(message.getRepeatedString(0), message.repeatedStringArray()[0]);
assertEquals(message.getRepeatedBytes(0), message.repeatedBytesArray()[0]);
assertEquals(message.getRepeatedgroup(0), message.repeatedgroupArray()[0]);
assertEquals(message.getRepeatedNestedMessage(0),
message.repeatedNestedMessageArray()[0]);
assertEquals(message.getRepeatedNestedEnum(0),
message.repeatedNestedEnumArray()[0]);
assertEquals(message.getRepeatedInt32(1), message.repeatedInt32Array()[1]);
assertEquals(message.getRepeatedInt64(1), message.repeatedInt64Array()[1]);
assertEquals(message.getRepeatedUint32(1), message.repeatedUint32Array()[1]);
assertEquals(message.getRepeatedUint64(1), message.repeatedUint64Array()[1]);
assertEquals(message.getRepeatedSint32(1), message.repeatedSint32Array()[1]);
assertEquals(message.getRepeatedSint64(1), message.repeatedSint64Array()[1]);
assertEquals(message.getRepeatedFixed32(1),
message.repeatedFixed32Array()[1]);
assertEquals(message.getRepeatedFixed64(1),
message.repeatedFixed64Array()[1]);
assertEquals(message.getRepeatedSfixed32(1),
message.repeatedSfixed32Array()[1]);
assertEquals(message.getRepeatedSfixed64(1),
message.repeatedSfixed64Array()[1]);
assertEquals(message.getRepeatedFloat(1), message.repeatedFloatArray()[1]);
assertEquals(message.getRepeatedDouble(1), message.repeatedDoubleArray()[1]);
assertEquals(message.getRepeatedBool(1), message.repeatedBoolArray()[1]);
assertEquals(message.getRepeatedString(1), message.repeatedStringArray()[1]);
assertEquals(message.getRepeatedBytes(1), message.repeatedBytesArray()[1]);
assertEquals(message.getRepeatedgroup(1), message.repeatedgroupArray()[1]);
assertEquals(message.getRepeatedNestedMessage(1),
message.repeatedNestedMessageArray()[1]);
assertEquals(message.getRepeatedNestedEnum(1),
message.repeatedNestedEnumArray()[1]);
}
function testDescriptor() {
var message = new proto2.TestAllTypes();
var descriptor = message.getDescriptor();
assertEquals('TestAllTypes', descriptor.getName());
assertEquals('TestAllTypes', descriptor.getFullName());
assertEquals(null, descriptor.getContainingType());
var nestedMessage = new proto2.TestAllTypes.NestedMessage();
var nestedDescriptor = nestedMessage.getDescriptor();
assertEquals('NestedMessage', nestedDescriptor.getName());
assertEquals('TestAllTypes.NestedMessage',
nestedDescriptor.getFullName());
assertEquals(descriptor, nestedDescriptor.getContainingType());
}
function testFieldDescriptor() {
var message = new proto2.TestAllTypes();
var descriptor = message.getDescriptor();
var fields = descriptor.getFields();
assertEquals(53, fields.length);
// Check the containing types.
for (var i = 0; i < fields.length; ++i) {
assertEquals(descriptor, fields[i].getContainingType());
}
// Check the field names.
assertEquals('optional_int32', fields[0].getName());
assertEquals('optional_int64', fields[1].getName());
assertEquals('optional_uint32', fields[2].getName());
assertEquals('optional_uint64', fields[3].getName());
assertEquals('optional_sint32', fields[4].getName());
assertEquals('optional_sint64', fields[5].getName());
assertEquals('optional_fixed32', fields[6].getName());
assertEquals('optional_fixed64', fields[7].getName());
assertEquals('optional_sfixed32', fields[8].getName());
assertEquals('optional_sfixed64', fields[9].getName());
assertEquals('optional_float', fields[10].getName());
assertEquals('optional_double', fields[11].getName());
assertEquals('optional_bool', fields[12].getName());
assertEquals('optional_string', fields[13].getName());
assertEquals('optional_bytes', fields[14].getName());
assertEquals('optionalgroup', fields[15].getName());
assertEquals('optional_nested_message', fields[16].getName());
assertEquals('optional_nested_enum', fields[17].getName());
assertEquals('repeated_int32', fields[18].getName());
assertEquals('repeated_int64', fields[19].getName());
assertEquals('repeated_uint32', fields[20].getName());
assertEquals('repeated_uint64', fields[21].getName());
assertEquals('repeated_sint32', fields[22].getName());
assertEquals('repeated_sint64', fields[23].getName());
assertEquals('repeated_fixed32', fields[24].getName());
assertEquals('repeated_fixed64', fields[25].getName());
assertEquals('repeated_sfixed32', fields[26].getName());
assertEquals('repeated_sfixed64', fields[27].getName());
assertEquals('repeated_float', fields[28].getName());
assertEquals('repeated_double', fields[29].getName());
assertEquals('repeated_bool', fields[30].getName());
assertEquals('repeated_string', fields[31].getName());
assertEquals('repeated_bytes', fields[32].getName());
assertEquals('repeatedgroup', fields[33].getName());
assertEquals('repeated_nested_message', fields[34].getName());
assertEquals('repeated_nested_enum', fields[35].getName());
assertEquals('optional_int64_number', fields[36].getName());
assertEquals('optional_int64_string', fields[37].getName());
assertEquals('repeated_int64_number', fields[38].getName());
assertEquals('repeated_int64_string', fields[39].getName());
assertEquals('packed_int32', fields[40].getName());
assertEquals('packed_int64', fields[41].getName());
assertEquals('packed_uint32', fields[42].getName());
assertEquals('packed_uint64', fields[43].getName());
assertEquals('packed_sint32', fields[44].getName());
assertEquals('packed_sint64', fields[45].getName());
assertEquals('packed_fixed32', fields[46].getName());
assertEquals('packed_fixed64', fields[47].getName());
assertEquals('packed_sfixed32', fields[48].getName());
assertEquals('packed_sfixed64', fields[49].getName());
assertEquals('packed_float', fields[50].getName());
assertEquals('packed_double', fields[51].getName());
assertEquals('packed_bool', fields[52].getName());
// Check the field types.
var FieldType = goog.proto2.FieldDescriptor.FieldType;
assertEquals(FieldType.INT32, fields[0].getFieldType());
assertEquals(FieldType.INT64, fields[1].getFieldType());
assertEquals(FieldType.UINT32, fields[2].getFieldType());
assertEquals(FieldType.UINT64, fields[3].getFieldType());
assertEquals(FieldType.SINT32, fields[4].getFieldType());
assertEquals(FieldType.SINT64, fields[5].getFieldType());
assertEquals(FieldType.FIXED32, fields[6].getFieldType());
assertEquals(FieldType.FIXED64, fields[7].getFieldType());
assertEquals(FieldType.SFIXED32, fields[8].getFieldType());
assertEquals(FieldType.SFIXED64, fields[9].getFieldType());
assertEquals(FieldType.FLOAT, fields[10].getFieldType());
assertEquals(FieldType.DOUBLE, fields[11].getFieldType());
assertEquals(FieldType.BOOL, fields[12].getFieldType());
assertEquals(FieldType.STRING, fields[13].getFieldType());
assertEquals(FieldType.BYTES, fields[14].getFieldType());
assertEquals(FieldType.GROUP, fields[15].getFieldType());
assertEquals(FieldType.MESSAGE, fields[16].getFieldType());
assertEquals(FieldType.ENUM, fields[17].getFieldType());
assertEquals(FieldType.INT32, fields[18].getFieldType());
assertEquals(FieldType.INT64, fields[19].getFieldType());
assertEquals(FieldType.UINT32, fields[20].getFieldType());
assertEquals(FieldType.UINT64, fields[21].getFieldType());
assertEquals(FieldType.SINT32, fields[22].getFieldType());
assertEquals(FieldType.SINT64, fields[23].getFieldType());
assertEquals(FieldType.FIXED32, fields[24].getFieldType());
assertEquals(FieldType.FIXED64, fields[25].getFieldType());
assertEquals(FieldType.SFIXED32, fields[26].getFieldType());
assertEquals(FieldType.SFIXED64, fields[27].getFieldType());
assertEquals(FieldType.FLOAT, fields[28].getFieldType());
assertEquals(FieldType.DOUBLE, fields[29].getFieldType());
assertEquals(FieldType.BOOL, fields[30].getFieldType());
assertEquals(FieldType.STRING, fields[31].getFieldType());
assertEquals(FieldType.BYTES, fields[32].getFieldType());
assertEquals(FieldType.GROUP, fields[33].getFieldType());
assertEquals(FieldType.MESSAGE, fields[34].getFieldType());
assertEquals(FieldType.ENUM, fields[35].getFieldType());
assertEquals(FieldType.INT64, fields[36].getFieldType());
assertEquals(FieldType.INT64, fields[37].getFieldType());
assertEquals(FieldType.INT64, fields[38].getFieldType());
assertEquals(FieldType.INT64, fields[39].getFieldType());
assertEquals(FieldType.INT32, fields[40].getFieldType());
assertEquals(FieldType.INT64, fields[41].getFieldType());
assertEquals(FieldType.UINT32, fields[42].getFieldType());
assertEquals(FieldType.UINT64, fields[43].getFieldType());
assertEquals(FieldType.SINT32, fields[44].getFieldType());
assertEquals(FieldType.SINT64, fields[45].getFieldType());
assertEquals(FieldType.FIXED32, fields[46].getFieldType());
assertEquals(FieldType.FIXED64, fields[47].getFieldType());
assertEquals(FieldType.SFIXED32, fields[48].getFieldType());
assertEquals(FieldType.SFIXED64, fields[49].getFieldType());
assertEquals(FieldType.FLOAT, fields[50].getFieldType());
assertEquals(FieldType.DOUBLE, fields[51].getFieldType());
assertEquals(FieldType.BOOL, fields[52].getFieldType());
// Check the field native types.
// Singular.
assertEquals(Number, fields[0].getNativeType());
assertEquals(String, fields[1].getNativeType()); // 64 bit values are strings.
assertEquals(Number, fields[2].getNativeType());
assertEquals(String, fields[3].getNativeType());
assertEquals(Number, fields[4].getNativeType());
assertEquals(String, fields[5].getNativeType());
assertEquals(Number, fields[6].getNativeType());
assertEquals(String, fields[7].getNativeType());
assertEquals(Number, fields[8].getNativeType());
assertEquals(String, fields[9].getNativeType());
assertEquals(Number, fields[10].getNativeType());
assertEquals(Number, fields[11].getNativeType());
assertEquals(Boolean, fields[12].getNativeType());
assertEquals(String, fields[13].getNativeType());
assertEquals(String, fields[14].getNativeType());
assertEquals(proto2.TestAllTypes.OptionalGroup, fields[15].getNativeType());
assertEquals(proto2.TestAllTypes.NestedMessage, fields[16].getNativeType());
assertEquals(proto2.TestAllTypes.NestedEnum, fields[17].getNativeType());
assertEquals(Number, fields[36].getNativeType()); // [jstype="number"]
assertEquals(String, fields[37].getNativeType());
// Repeated.
assertEquals(Number, fields[18].getNativeType());
assertEquals(String, fields[19].getNativeType());
assertEquals(Number, fields[20].getNativeType());
assertEquals(String, fields[21].getNativeType());
assertEquals(Number, fields[22].getNativeType());
assertEquals(String, fields[23].getNativeType());
assertEquals(Number, fields[24].getNativeType());
assertEquals(String, fields[25].getNativeType());
assertEquals(Number, fields[26].getNativeType());
assertEquals(String, fields[27].getNativeType());
assertEquals(Number, fields[28].getNativeType());
assertEquals(Number, fields[29].getNativeType());
assertEquals(Boolean, fields[30].getNativeType());
assertEquals(String, fields[31].getNativeType());
assertEquals(String, fields[32].getNativeType());
assertEquals(proto2.TestAllTypes.RepeatedGroup, fields[33].getNativeType());
assertEquals(proto2.TestAllTypes.NestedMessage, fields[34].getNativeType());
assertEquals(proto2.TestAllTypes.NestedEnum, fields[35].getNativeType());
assertEquals(Number, fields[38].getNativeType()); // [jstype="number"]
assertEquals(String, fields[39].getNativeType());
// Packed (only numeric types can be packed).
assertEquals(Number, fields[40].getNativeType());
assertEquals(Number, fields[41].getNativeType());
assertEquals(Number, fields[42].getNativeType());
assertEquals(Number, fields[43].getNativeType());
assertEquals(Number, fields[44].getNativeType());
assertEquals(Number, fields[45].getNativeType());
assertEquals(Number, fields[46].getNativeType());
assertEquals(Number, fields[47].getNativeType());
assertEquals(Number, fields[48].getNativeType());
assertEquals(Number, fields[49].getNativeType());
assertEquals(Number, fields[50].getNativeType());
assertEquals(Number, fields[51].getNativeType());
assertEquals(Boolean, fields[52].getNativeType());
}
function testUnknown() {
var message = new proto2.TestAllTypes();
// Set some unknown fields.
message.setUnknown(1000, 101);
message.setUnknown(1001, -102);
message.setUnknown(1002, true);
message.setUnknown(1003, 'abcd');
message.setUnknown(1004, ['he', 'llo']);
// Ensure we find them all.
var count = 0;
message.forEachUnknown(function(tag, value) {
if (tag == 1000) {
assertEquals(101, value);
}
if (tag == 1001) {
assertEquals(-102, value);
}
if (tag == 1002) {
assertEquals(true, value);
}
if (tag == 1003) {
assertEquals('abcd', value);
}
if (tag == 1004) {
assertEquals('he', value[0]);
assertEquals('llo', value[1]);
}
count++;
});
assertEquals(5, count);
}
function testReflection() {
var message = new proto2.TestAllTypes();
var descriptor = message.getDescriptor();
var optionalInt = descriptor.findFieldByName('optional_int32');
var optionalString = descriptor.findFieldByName('optional_string');
var repeatedInt64 = descriptor.findFieldByName('repeated_int64');
var optionalWrong = descriptor.findFieldByName('foo_bar');
assertFalse(optionalInt == null);
assertFalse(optionalString == null);
assertFalse(repeatedInt64 == null);
assertTrue(optionalWrong == null);
// Check to ensure the fields are empty.
assertFalse(message.has(optionalInt));
assertFalse(message.has(optionalString));
assertFalse(message.has(repeatedInt64));
assertEquals(0, message.arrayOf(repeatedInt64).length);
// Check default values.
assertEquals(0, message.getOrDefault(optionalInt));
assertEquals('', message.getOrDefault(optionalString));
// Set some of the fields.
message.set(optionalString, 'hello!');
message.add(repeatedInt64, '101');
message.add(repeatedInt64, '102');
// Check the fields.
assertFalse(message.has(optionalInt));
assertTrue(message.has(optionalString));
assertTrue(message.hasOptionalString());
assertTrue(message.has(repeatedInt64));
assertTrue(message.hasRepeatedInt64());
// Check the values.
assertEquals('hello!', message.get(optionalString));
assertEquals('hello!', message.getOptionalString());
assertEquals('101', message.get(repeatedInt64, 0));
assertEquals('102', message.get(repeatedInt64, 1));
assertEquals('101', message.getRepeatedInt64(0));
assertEquals('102', message.getRepeatedInt64(1));
// Check the count.
assertEquals(0, message.countOf(optionalInt));
assertEquals(1, message.countOf(optionalString));
assertEquals(1, message.optionalStringCount());
assertEquals(2, message.countOf(repeatedInt64));
assertEquals(2, message.repeatedInt64Count());
// Check the array.
assertEquals(2, message.arrayOf(repeatedInt64).length);
assertEquals(message.get(repeatedInt64, 0),
message.arrayOf(repeatedInt64)[0]);
assertEquals(message.get(repeatedInt64, 1),
message.arrayOf(repeatedInt64)[1]);
}
function testDefaultValuesForMessages() {
var message = new proto2.TestDefaultParent();
// Ideally this object would be immutable, but the current API does not
// enforce that behavior, so get**OrDefault returns a new instance every time.
var child = message.getChildOrDefault();
child.setFoo(false);
// Changing the value returned by get**OrDefault does not actually change
// the value stored in the parent message.
assertFalse(message.hasChild());
assertNull(message.getChild());
var message2 = new proto2.TestDefaultParent();
var child2 = message2.getChildOrDefault();
assertNull(message2.getChild());
// The parent message returns a different object for the default.
assertNotEquals(child, child2);
// You've only changed the value of child, so child2 should be unaffected.
assertFalse(child2.hasFoo());
assertTrue(child2.getFooOrDefault());
}
@@ -0,0 +1,182 @@
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
//
// Licensed 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.
/**
* @fileoverview Base class for all Protocol Buffer 2 serializers.
*/
goog.provide('goog.proto2.Serializer');
goog.require('goog.asserts');
goog.require('goog.proto2.FieldDescriptor');
goog.require('goog.proto2.Message');
/**
* Abstract base class for PB2 serializers. A serializer is a class which
* implements the serialization and deserialization of a Protocol Buffer Message
* to/from a specific format.
*
* @constructor
*/
goog.proto2.Serializer = function() {};
/**
* @define {boolean} Whether to decode and convert symbolic enum values to
* actual enum values or leave them as strings.
*/
goog.define('goog.proto2.Serializer.DECODE_SYMBOLIC_ENUMS', false);
/**
* Serializes a message to the expected format.
*
* @param {goog.proto2.Message} message The message to be serialized.
*
* @return {*} The serialized form of the message.
*/
goog.proto2.Serializer.prototype.serialize = goog.abstractMethod;
/**
* Returns the serialized form of the given value for the given field if the
* field is a Message or Group and returns the value unchanged otherwise, except
* for Infinity, -Infinity and NaN numerical values which are converted to
* string representation.
*
* @param {goog.proto2.FieldDescriptor} field The field from which this
* value came.
*
* @param {*} value The value of the field.
*
* @return {*} The value.
* @protected
*/
goog.proto2.Serializer.prototype.getSerializedValue = function(field, value) {
if (field.isCompositeType()) {
return this.serialize(/** @type {goog.proto2.Message} */ (value));
} else if (goog.isNumber(value) && !isFinite(value)) {
return value.toString();
} else {
return value;
}
};
/**
* Deserializes a message from the expected format.
*
* @param {goog.proto2.Descriptor} descriptor The descriptor of the message
* to be created.
* @param {*} data The data of the message.
*
* @return {!goog.proto2.Message} The message created.
*/
goog.proto2.Serializer.prototype.deserialize = function(descriptor, data) {
var message = descriptor.createMessageInstance();
this.deserializeTo(message, data);
goog.asserts.assert(message instanceof goog.proto2.Message);
return message;
};
/**
* Deserializes a message from the expected format and places the
* data in the message.
*
* @param {goog.proto2.Message} message The message in which to
* place the information.
* @param {*} data The data of the message.
*/
goog.proto2.Serializer.prototype.deserializeTo = goog.abstractMethod;
/**
* Returns the deserialized form of the given value for the given field if the
* field is a Message or Group and returns the value, converted or unchanged,
* for primitive field types otherwise.
*
* @param {goog.proto2.FieldDescriptor} field The field from which this
* value came.
*
* @param {*} value The value of the field.
*
* @return {*} The value.
* @protected
*/
goog.proto2.Serializer.prototype.getDeserializedValue = function(field, value) {
// Composite types are deserialized recursively.
if (field.isCompositeType()) {
if (value instanceof goog.proto2.Message) {
return value;
}
return this.deserialize(field.getFieldMessageType(), value);
}
// Decode enum values.
if (field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.ENUM) {
// If it's a string, get enum value by name.
// NB: In order this feature to work, property renaming should be turned off
// for the respective enums.
if (goog.proto2.Serializer.DECODE_SYMBOLIC_ENUMS && goog.isString(value)) {
// enumType is a regular Javascript enum as defined in field's metadata.
var enumType = field.getNativeType();
if (enumType.hasOwnProperty(value)) {
return enumType[value];
}
}
// Return unknown values as is for backward compatibility.
return value;
}
// Return the raw value if the field does not allow the JSON input to be
// converted.
if (!field.deserializationConversionPermitted()) {
return value;
}
// Convert to native type of field. Return the converted value or fall
// through to return the raw value. The JSON encoding of int64 value 123
// might be either the number 123 or the string "123". The field native type
// could be either Number or String (depending on field options in the .proto
// file). All four combinations should work correctly.
var nativeType = field.getNativeType();
if (nativeType === String) {
// JSON numbers can be converted to strings.
if (goog.isNumber(value)) {
return String(value);
}
} else if (nativeType === Number) {
// JSON strings are sometimes used for large integer numeric values, as well
// as Infinity, -Infinity and NaN.
if (goog.isString(value)) {
// Handle +/- Infinity and NaN values.
if (value === 'Infinity' || value === '-Infinity' || value === 'NaN') {
return Number(value);
}
// Validate the string. If the string is not an integral number, we would
// rather have an assertion or error in the caller than a mysterious NaN
// value.
if (/^-?[0-9]+$/.test(value)) {
return Number(value);
}
}
}
return value;
};
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<!--
Copyright 2011 The Closure Library Authors. All Rights Reserved.
Use of this source code is governed by the Apache License, Version 2.0.
See the COPYING file for details.
-->
<!--
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Closure Unit Tests - goog.proto2 - textformatserializer.js</title>
<script src="../base.js"></script>
</head>
<body>
<script>
goog.require('goog.proto2.TextFormatSerializerTest');
</script>
</body>
</html>
@@ -0,0 +1,807 @@
// Copyright 2012 The Closure Library Authors. All Rights Reserved.
//
// Licensed 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.
/**
* @fileoverview Unit tests for goog.proto2.TextFormatSerializer.
*
*/
/** @suppress {extraProvide} */
goog.provide('goog.proto2.TextFormatSerializerTest');
goog.require('goog.proto2.ObjectSerializer');
goog.require('goog.proto2.TextFormatSerializer');
goog.require('goog.testing.jsunit');
goog.require('proto2.TestAllTypes');
goog.setTestOnly('goog.proto2.TextFormatSerializerTest');
function testSerialization() {
var message = new proto2.TestAllTypes();
// Set the fields.
// Singular.
message.setOptionalInt32(101);
message.setOptionalUint32(103);
message.setOptionalSint32(105);
message.setOptionalFixed32(107);
message.setOptionalSfixed32(109);
message.setOptionalInt64('102');
message.setOptionalFloat(111.5);
message.setOptionalDouble(112.5);
message.setOptionalBool(true);
message.setOptionalString('test');
message.setOptionalBytes('abcd');
var group = new proto2.TestAllTypes.OptionalGroup();
group.setA(111);
message.setOptionalgroup(group);
var nestedMessage = new proto2.TestAllTypes.NestedMessage();
nestedMessage.setB(112);
message.setOptionalNestedMessage(nestedMessage);
message.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
// Repeated.
message.addRepeatedInt32(201);
message.addRepeatedInt32(202);
// Serialize to a simplified text format.
var simplified = new goog.proto2.TextFormatSerializer().serialize(message);
var expected = 'optional_int32: 101\n' +
'optional_int64: 102\n' +
'optional_uint32: 103\n' +
'optional_sint32: 105\n' +
'optional_fixed32: 107\n' +
'optional_sfixed32: 109\n' +
'optional_float: 111.5\n' +
'optional_double: 112.5\n' +
'optional_bool: true\n' +
'optional_string: "test"\n' +
'optional_bytes: "abcd"\n' +
'optionalgroup {\n' +
' a: 111\n' +
'}\n' +
'optional_nested_message {\n' +
' b: 112\n' +
'}\n' +
'optional_nested_enum: FOO\n' +
'repeated_int32: 201\n' +
'repeated_int32: 202\n';
assertEquals(expected, simplified);
}
function testSerializationOfUnknown() {
var nestedUnknown = new proto2.TestAllTypes();
var message = new proto2.TestAllTypes();
// Set the fields.
// Known.
message.setOptionalInt32(101);
message.addRepeatedInt32(201);
message.addRepeatedInt32(202);
nestedUnknown.addRepeatedInt32(301);
nestedUnknown.addRepeatedInt32(302);
// Unknown.
message.setUnknown(1000, 301);
message.setUnknown(1001, 302);
message.setUnknown(1002, 'hello world');
message.setUnknown(1002, nestedUnknown);
nestedUnknown.setUnknown(2000, 401);
// Serialize.
var simplified = new goog.proto2.TextFormatSerializer().serialize(message);
var expected = 'optional_int32: 101\n' +
'repeated_int32: 201\n' +
'repeated_int32: 202\n' +
'1000: 301\n' +
'1001: 302\n' +
'1002 {\n' +
' repeated_int32: 301\n' +
' repeated_int32: 302\n' +
' 2000: 401\n' +
'}\n';
assertEquals(expected, simplified);
}
function testSerializationOfUnknownParsedFromObject() {
// Construct the object-serialized representation of the message constructed
// programmatically in the test above.
var serialized = {
1: 101,
31: [201, 202],
1000: 301,
1001: 302,
1002: {
31: [301, 302],
2000: 401
}
};
// Deserialize that representation into a TestAllTypes message.
var objectSerializer = new goog.proto2.ObjectSerializer();
var message = new proto2.TestAllTypes();
objectSerializer.deserializeTo(message, serialized);
// Check that the text format matches what we expect.
var simplified = new goog.proto2.TextFormatSerializer().serialize(message);
var expected = (
'optional_int32: 101\n' +
'repeated_int32: 201\n' +
'repeated_int32: 202\n' +
'1000: 301\n' +
'1001: 302\n' +
'1002 {\n' +
' 31: 301\n' +
' 31: 302\n' +
' 2000: 401\n' +
'}\n'
);
assertEquals(expected, simplified);
}
/**
* Asserts that the given string value parses into the given set of tokens.
* @param {string} value The string value to parse.
* @param {Array<Object> | Object} tokens The tokens to check against. If not
* an array, a single token is expected.
* @param {boolean=} opt_ignoreWhitespace Whether whitespace tokens should be
* skipped by the tokenizer.
*/
function assertTokens(value, tokens, opt_ignoreWhitespace) {
var tokenizer = new goog.proto2.TextFormatSerializer.Tokenizer_(
value, opt_ignoreWhitespace);
var tokensFound = [];
while (tokenizer.next()) {
tokensFound.push(tokenizer.getCurrent());
}
if (goog.typeOf(tokens) != 'array') {
tokens = [tokens];
}
assertEquals(tokens.length, tokensFound.length);
for (var i = 0; i < tokens.length; ++i) {
assertToken(tokens[i], tokensFound[i]);
}
}
function assertToken(expected, found) {
assertEquals(expected.type, found.type);
if (expected.value) {
assertEquals(expected.value, found.value);
}
}
function testTokenizer() {
var types = goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes;
assertTokens('{ 123 }', [
{ type: types.OPEN_BRACE },
{ type: types.WHITESPACE, value: ' ' },
{ type: types.NUMBER, value: '123' },
{ type: types.WHITESPACE, value: ' '},
{ type: types.CLOSE_BRACE }
]);
// The c++ proto serializer might represent a float in exponential
// notation:
assertTokens('{ 1.2345e+3 }', [
{ type: types.OPEN_BRACE },
{ type: types.WHITESPACE, value: ' ' },
{ type: types.NUMBER, value: '1.2345e+3' },
{ type: types.WHITESPACE, value: ' '},
{ type: types.CLOSE_BRACE }
]);
}
function testTokenizerExponentialFloatProblem() {
var input = 'merchant: { # blah blah\n' +
' total_price: 3.2186e+06 # 3_218_600; 3.07Mi\n' +
' taxes : 2.17199e+06\n' +
'}';
var types = goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes;
assertTokens(input, [
{ type: types.IDENTIFIER, value: 'merchant' },
{ type: types.COLON, value: ':' },
{ type: types.OPEN_BRACE, value: '{' },
{ type: types.COMMENT, value: '# blah blah' },
{ type: types.IDENTIFIER, value: 'total_price' },
{ type: types.COLON, value: ':' },
{ type: types.NUMBER, value: '3.2186e+06' },
{ type: types.COMMENT, value: '# 3_218_600; 3.07Mi' },
{ type: types.IDENTIFIER, value: 'taxes' },
{ type: types.COLON, value: ':' },
{ type: types.NUMBER, value: '2.17199e+06' },
{ type: types.CLOSE_BRACE, value: '}' }
],
true);
}
function testTokenizerNoWhitespace() {
var types = goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes;
assertTokens('{ "hello world" }', [
{ type: types.OPEN_BRACE },
{ type: types.STRING, value: '"hello world"' },
{ type: types.CLOSE_BRACE }
], true);
}
function assertIdentifier(identifier) {
var types = goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes;
assertTokens(identifier, { type: types.IDENTIFIER, value: identifier });
}
function assertComment(comment) {
var types = goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes;
assertTokens(comment, { type: types.COMMENT, value: comment });
}
function assertString(str) {
var types = goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes;
assertTokens(str, { type: types.STRING, value: str });
}
function assertNumber(num) {
num = num.toString();
var types = goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes;
assertTokens(num, { type: types.NUMBER, value: num });
}
function testTokenizerSingleTokens() {
var types = goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes;
assertTokens('{', { type: types.OPEN_BRACE });
assertTokens('}', { type: types.CLOSE_BRACE });
assertTokens('<', { type: types.OPEN_TAG });
assertTokens('>', { type: types.CLOSE_TAG });
assertTokens(':', { type: types.COLON });
assertTokens(',', { type: types.COMMA });
assertTokens(';', { type: types.SEMI });
assertIdentifier('abcd');
assertIdentifier('Abcd');
assertIdentifier('ABcd');
assertIdentifier('ABcD');
assertIdentifier('a123nc');
assertIdentifier('a45_bC');
assertIdentifier('A45_bC');
assertIdentifier('inf');
assertIdentifier('infinity');
assertIdentifier('nan');
assertNumber(0);
assertNumber(10);
assertNumber(123);
assertNumber(1234);
assertNumber(123.56);
assertNumber(-124);
assertNumber(-1234);
assertNumber(-123.56);
assertNumber('123f');
assertNumber('123.6f');
assertNumber('-123f');
assertNumber('-123.8f');
assertNumber('0x1234');
assertNumber('0x12ac34');
assertNumber('0x49e281db686fb');
// Floating point numbers might be serialized in exponential
// notation:
assertNumber('1.2345e+3');
assertNumber('1.2345e3');
assertNumber('1.2345e-2');
assertString('""');
assertString('"hello world"');
assertString('"hello # world"');
assertString('"hello #\\" world"');
assertString('"|"');
assertString('"\\"\\""');
assertString('"\\"foo\\""');
assertString('"\\"foo\\" and \\"bar\\""');
assertString('"foo \\"and\\" bar"');
assertComment('# foo bar baz');
assertComment('# foo ## bar baz');
assertComment('# foo "bar" baz');
}
function testSerializationOfStringWithQuotes() {
var nestedUnknown = new proto2.TestAllTypes();
var message = new proto2.TestAllTypes();
message.setOptionalString('hello "world"');
// Serialize.
var simplified = new goog.proto2.TextFormatSerializer().serialize(message);
var expected = 'optional_string: "hello \\"world\\""\n';
assertEquals(expected, simplified);
}
function testDeserialization() {
var message = new proto2.TestAllTypes();
var value = 'optional_int32: 101\n' +
'repeated_int32: 201\n' +
'repeated_int32: 202\n' +
'optional_float: 123.4';
new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
assertEquals(101, message.getOptionalInt32());
assertEquals(201, message.getRepeatedInt32(0));
assertEquals(202, message.getRepeatedInt32(1));
assertEquals(123.4, message.getOptionalFloat());
}
function testDeserializationOfList() {
var message = new proto2.TestAllTypes();
var value = 'optional_int32: 101\n' +
'repeated_int32: [201, 202]\n' +
'optional_float: 123.4';
new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
assertEquals(101, message.getOptionalInt32());
assertEquals(201, message.getRepeatedInt32(0));
assertEquals(123.4, message.getOptionalFloat());
}
function testDeserializationOfIntegerAsHexadecimalString() {
var message = new proto2.TestAllTypes();
var value = 'optional_int32: 0x1\n' +
'optional_sint32: 0xf\n' +
'optional_uint32: 0xffffffff\n' +
'repeated_int32: [0x0, 0xff]\n';
new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
assertEquals(1, message.getOptionalInt32());
assertEquals(15, message.getOptionalSint32());
assertEquals(4294967295, message.getOptionalUint32());
assertEquals(0, message.getRepeatedInt32(0));
assertEquals(255, message.getRepeatedInt32(1));
}
function testDeserializationOfInt64AsHexadecimalString() {
var message = new proto2.TestAllTypes();
var value = 'optional_int64: 0xf';
new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
assertEquals('0xf', message.getOptionalInt64());
}
function testDeserializationOfZeroFalseAndEmptyString() {
var message = new proto2.TestAllTypes();
var value = 'optional_int32: 0\n' +
'optional_bool: false\n' +
'optional_string: ""';
new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
assertEquals(0, message.getOptionalInt32());
assertEquals(false, message.getOptionalBool());
assertEquals('', message.getOptionalString());
}
function testDeserializationOfConcatenatedString() {
var message = new proto2.TestAllTypes();
var value = 'optional_int32: 123\n' +
'optional_string:\n' +
' "FirstLine"\n' +
' "SecondLine"\n' +
'optional_float: 456.7';
new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
assertEquals(123, message.getOptionalInt32());
assertEquals('FirstLineSecondLine', message.getOptionalString());
assertEquals(456.7, message.getOptionalFloat());
}
function testDeserializationSkipComment() {
var message = new proto2.TestAllTypes();
var value = 'optional_int32: 101\n' +
'repeated_int32: 201\n' +
'# Some comment.\n' +
'repeated_int32: 202\n' +
'optional_float: 123.4';
var parser = new goog.proto2.TextFormatSerializer.Parser();
assertTrue(parser.parse(message, value));
assertEquals(101, message.getOptionalInt32());
assertEquals(201, message.getRepeatedInt32(0));
assertEquals(202, message.getRepeatedInt32(1));
assertEquals(123.4, message.getOptionalFloat());
}
function testDeserializationSkipTrailingComment() {
var message = new proto2.TestAllTypes();
var value = 'optional_int32: 101\n' +
'repeated_int32: 201\n' +
'repeated_int32: 202 # Some trailing comment.\n' +
'optional_float: 123.4';
var parser = new goog.proto2.TextFormatSerializer.Parser();
assertTrue(parser.parse(message, value));
assertEquals(101, message.getOptionalInt32());
assertEquals(201, message.getRepeatedInt32(0));
assertEquals(202, message.getRepeatedInt32(1));
assertEquals(123.4, message.getOptionalFloat());
}
function testDeserializationSkipUnknown() {
var message = new proto2.TestAllTypes();
var value = 'optional_int32: 101\n' +
'repeated_int32: 201\n' +
'some_unknown: true\n' +
'repeated_int32: 202\n' +
'optional_float: 123.4';
var parser = new goog.proto2.TextFormatSerializer.Parser();
assertTrue(parser.parse(message, value, true));
assertEquals(101, message.getOptionalInt32());
assertEquals(201, message.getRepeatedInt32(0));
assertEquals(202, message.getRepeatedInt32(1));
assertEquals(123.4, message.getOptionalFloat());
}
function testDeserializationSkipUnknownList() {
var message = new proto2.TestAllTypes();
var value = 'optional_int32: 101\n' +
'repeated_int32: 201\n' +
'some_unknown: [true, 1, 201, "hello"]\n' +
'repeated_int32: 202\n' +
'optional_float: 123.4';
var parser = new goog.proto2.TextFormatSerializer.Parser();
assertTrue(parser.parse(message, value, true));
assertEquals(101, message.getOptionalInt32());
assertEquals(201, message.getRepeatedInt32(0));
assertEquals(202, message.getRepeatedInt32(1));
assertEquals(123.4, message.getOptionalFloat());
}
function testDeserializationSkipUnknownNested() {
var message = new proto2.TestAllTypes();
var value = 'optional_int32: 101\n' +
'repeated_int32: 201\n' +
'some_unknown: <\n' +
' a: 1\n' +
' b: 2\n' +
'>\n' +
'repeated_int32: 202\n' +
'optional_float: 123.4';
var parser = new goog.proto2.TextFormatSerializer.Parser();
assertTrue(parser.parse(message, value, true));
assertEquals(101, message.getOptionalInt32());
assertEquals(201, message.getRepeatedInt32(0));
assertEquals(202, message.getRepeatedInt32(1));
assertEquals(123.4, message.getOptionalFloat());
}
function testDeserializationSkipUnknownNestedInvalid() {
var message = new proto2.TestAllTypes();
var value = 'optional_int32: 101\n' +
'repeated_int32: 201\n' +
'some_unknown: <\n' +
' a: \n' + // Missing value.
' b: 2\n' +
'>\n' +
'repeated_int32: 202\n' +
'optional_float: 123.4';
var parser = new goog.proto2.TextFormatSerializer.Parser();
assertFalse(parser.parse(message, value, true));
}
function testDeserializationSkipUnknownNestedInvalid2() {
var message = new proto2.TestAllTypes();
var value = 'optional_int32: 101\n' +
'repeated_int32: 201\n' +
'some_unknown: <\n' +
' a: 2\n' +
' b: 2\n' +
'}\n' + // Delimiter mismatch
'repeated_int32: 202\n' +
'optional_float: 123.4';
var parser = new goog.proto2.TextFormatSerializer.Parser();
assertFalse(parser.parse(message, value, true));
}
function testDeserializationLegacyFormat() {
var message = new proto2.TestAllTypes();
var value = 'optional_int32: 101,\n' +
'repeated_int32: 201,\n' +
'repeated_int32: 202;\n' +
'optional_float: 123.4';
new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
assertEquals(101, message.getOptionalInt32());
assertEquals(201, message.getRepeatedInt32(0));
assertEquals(202, message.getRepeatedInt32(1));
assertEquals(123.4, message.getOptionalFloat());
}
function testDeserializationVariedNumbers() {
var message = new proto2.TestAllTypes();
var value = (
'repeated_int32: 23\n' +
'repeated_int32: -3\n' +
'repeated_int32: 0xdeadbeef\n' +
'repeated_float: 123.0\n' +
'repeated_float: -3.27\n' +
'repeated_float: -35.5f\n'
);
new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
assertEquals(23, message.getRepeatedInt32(0));
assertEquals(-3, message.getRepeatedInt32(1));
assertEquals(3735928559, message.getRepeatedInt32(2));
assertEquals(123.0, message.getRepeatedFloat(0));
assertEquals(-3.27, message.getRepeatedFloat(1));
assertEquals(-35.5, message.getRepeatedFloat(2));
}
function testDeserializationScientificNotation() {
var message = new proto2.TestAllTypes();
var value = 'repeated_float: 1.1e5\n' +
'repeated_float: 1.1e-5\n' +
'repeated_double: 1.1e5\n' +
'repeated_double: 1.1e-5\n';
new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
assertEquals(1.1e5, message.getRepeatedFloat(0));
assertEquals(1.1e-5, message.getRepeatedFloat(1));
assertEquals(1.1e5, message.getRepeatedDouble(0));
assertEquals(1.1e-5, message.getRepeatedDouble(1));
}
function testParseNumericalConstant() {
var parseNumericalConstant =
goog.proto2.TextFormatSerializer.Parser.parseNumericalConstant_;
assertEquals(Infinity, parseNumericalConstant('inf'));
assertEquals(Infinity, parseNumericalConstant('inff'));
assertEquals(Infinity, parseNumericalConstant('infinity'));
assertEquals(Infinity, parseNumericalConstant('infinityf'));
assertEquals(Infinity, parseNumericalConstant('Infinityf'));
assertEquals(-Infinity, parseNumericalConstant('-inf'));
assertEquals(-Infinity, parseNumericalConstant('-inff'));
assertEquals(-Infinity, parseNumericalConstant('-infinity'));
assertEquals(-Infinity, parseNumericalConstant('-infinityf'));
assertEquals(-Infinity, parseNumericalConstant('-Infinity'));
assertNull(parseNumericalConstant('-infin'));
assertNull(parseNumericalConstant('infin'));
assertNull(parseNumericalConstant('-infinite'));
assertNull(parseNumericalConstant('-infin'));
assertNull(parseNumericalConstant('infin'));
assertNull(parseNumericalConstant('-infinite'));
assertTrue(isNaN(parseNumericalConstant('Nan')));
assertTrue(isNaN(parseNumericalConstant('NaN')));
assertTrue(isNaN(parseNumericalConstant('NAN')));
assertTrue(isNaN(parseNumericalConstant('nan')));
assertTrue(isNaN(parseNumericalConstant('nanf')));
assertTrue(isNaN(parseNumericalConstant('NaNf')));
assertEquals(Number.POSITIVE_INFINITY, parseNumericalConstant('infinity'));
assertEquals(Number.NEGATIVE_INFINITY, parseNumericalConstant('-inf'));
assertEquals(Number.NEGATIVE_INFINITY, parseNumericalConstant('-infinity'));
assertNull(parseNumericalConstant('na'));
assertNull(parseNumericalConstant('-nan'));
assertNull(parseNumericalConstant('none'));
}
function testDeserializationOfNumericalConstants() {
var message = new proto2.TestAllTypes();
var value = (
'repeated_float: inf\n' +
'repeated_float: -inf\n' +
'repeated_float: nan\n' +
'repeated_float: 300.2\n'
);
new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
assertEquals(Infinity, message.getRepeatedFloat(0));
assertEquals(-Infinity, message.getRepeatedFloat(1));
assertTrue(isNaN(message.getRepeatedFloat(2)));
assertEquals(300.2, message.getRepeatedFloat(3));
}
var floatFormatCases = [{given: '1.69e+06', expect: 1.69e+06},
{given: '1.69e6', expect: 1.69e+06},
{given: '2.468e-2', expect: 0.02468}
];
function testGetNumberFromStringExponentialNotation() {
for (var i = 0; i < floatFormatCases.length; ++i) {
var thistest = floatFormatCases[i];
var result = goog.proto2.TextFormatSerializer.Parser.
getNumberFromString_(thistest.given);
assertEquals(thistest.expect, result);
}
}
function testDeserializationExponentialFloat() {
var parser = new goog.proto2.TextFormatSerializer.Parser();
for (var i = 0; i < floatFormatCases.length; ++i) {
var thistest = floatFormatCases[i];
var message = new proto2.TestAllTypes();
var value = 'optional_float: ' + thistest.given;
assertTrue(parser.parse(message, value, true));
assertEquals(thistest.expect, message.getOptionalFloat());
}
}
function testGetNumberFromString() {
var getNumberFromString =
goog.proto2.TextFormatSerializer.Parser.getNumberFromString_;
assertEquals(3735928559, getNumberFromString('0xdeadbeef'));
assertEquals(4276215469, getNumberFromString('0xFEE1DEAD'));
assertEquals(123.1, getNumberFromString('123.1'));
assertEquals(123.0, getNumberFromString('123.0'));
assertEquals(-29.3, getNumberFromString('-29.3f'));
assertEquals(23, getNumberFromString('23'));
assertEquals(-3, getNumberFromString('-3'));
assertEquals(-3.27, getNumberFromString('-3.27'));
assertThrows(goog.partial(getNumberFromString, 'cat'));
assertThrows(goog.partial(getNumberFromString, 'NaN'));
assertThrows(goog.partial(getNumberFromString, 'inf'));
}
function testDeserializationError() {
var message = new proto2.TestAllTypes();
var value = 'optional_int33: 101\n';
var result =
new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
assertEquals(result, 'Unknown field: optional_int33');
}
function testNestedDeserialization() {
var message = new proto2.TestAllTypes();
var value = 'optional_int32: 101\n' +
'optional_nested_message: {\n' +
' b: 301\n' +
'}';
new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
assertEquals(101, message.getOptionalInt32());
assertEquals(301, message.getOptionalNestedMessage().getB());
}
function testNestedDeserializationLegacyFormat() {
var message = new proto2.TestAllTypes();
var value = 'optional_int32: 101\n' +
'optional_nested_message: <\n' +
' b: 301\n' +
'>';
new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
assertEquals(101, message.getOptionalInt32());
assertEquals(301, message.getOptionalNestedMessage().getB());
}
function testBidirectional() {
var message = new proto2.TestAllTypes();
// Set the fields.
// Singular.
message.setOptionalInt32(101);
message.setOptionalInt64('102');
message.setOptionalUint32(103);
message.setOptionalUint64('104');
message.setOptionalSint32(105);
message.setOptionalSint64('106');
message.setOptionalFixed32(107);
message.setOptionalFixed64('108');
message.setOptionalSfixed32(109);
message.setOptionalSfixed64('110');
message.setOptionalFloat(111.5);
message.setOptionalDouble(112.5);
message.setOptionalBool(true);
message.setOptionalString('test');
message.setOptionalBytes('abcd');
var group = new proto2.TestAllTypes.OptionalGroup();
group.setA(111);
message.setOptionalgroup(group);
var nestedMessage = new proto2.TestAllTypes.NestedMessage();
nestedMessage.setB(112);
message.setOptionalNestedMessage(nestedMessage);
message.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
// Repeated.
message.addRepeatedInt32(201);
message.addRepeatedInt32(202);
message.addRepeatedString('hello "world"');
// Serialize the message to text form.
var serializer = new goog.proto2.TextFormatSerializer();
var textform = serializer.serialize(message);
// Create a copy and deserialize into the copy.
var copy = new proto2.TestAllTypes();
serializer.deserializeTo(copy, textform);
// Assert that the messages are structurally equivalent.
assertTrue(copy.equals(message));
}
function testBidirectional64BitNumber() {
var message = new proto2.TestAllTypes();
message.setOptionalInt64Number(10000000);
message.setOptionalInt64String('200000000000000000');
// Serialize the message to text form.
var serializer = new goog.proto2.TextFormatSerializer();
var textform = serializer.serialize(message);
// Create a copy and deserialize into the copy.
var copy = new proto2.TestAllTypes();
serializer.deserializeTo(copy, textform);
// Assert that the messages are structurally equivalent.
assertTrue(copy.equals(message));
}
function testUseEnumValues() {
var message = new proto2.TestAllTypes();
message.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
var serializer = new goog.proto2.TextFormatSerializer(false, true);
var textform = serializer.serialize(message);
var expected = 'optional_nested_enum: 0\n';
assertEquals(expected, textform);
var deserializedMessage = new proto2.TestAllTypes();
serializer.deserializeTo(deserializedMessage, textform);
assertEquals(
proto2.TestAllTypes.NestedEnum.FOO,
deserializedMessage.getOptionalNestedEnum());
}
@@ -0,0 +1,54 @@
// Copyright 2009 The Closure Library Authors. All Rights Reserved.
//
// Licensed 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.
/**
* @fileoverview Utility methods for Protocol Buffer 2 implementation.
*/
goog.provide('goog.proto2.Util');
goog.require('goog.asserts');
/**
* @define {boolean} Defines a PBCHECK constant that can be turned off by
* clients of PB2. This for is clients that do not want assertion/checking
* running even in non-COMPILED builds.
*/
goog.define('goog.proto2.Util.PBCHECK', !COMPILED);
/**
* Asserts that the given condition is true, if and only if the PBCHECK
* flag is on.
*
* @param {*} condition The condition to check.
* @param {string=} opt_message Error message in case of failure.
* @throws {Error} Assertion failed, the condition evaluates to false.
*/
goog.proto2.Util.assert = function(condition, opt_message) {
if (goog.proto2.Util.PBCHECK) {
goog.asserts.assert(condition, opt_message);
}
};
/**
* Returns true if debug assertions (checks) are on.
*
* @return {boolean} The value of the PBCHECK constant.
*/
goog.proto2.Util.conductChecks = function() {
return goog.proto2.Util.PBCHECK;
};