Adding mapbox-gl branch
This commit is contained in:
@@ -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;
|
||||
};
|
||||
Reference in New Issue
Block a user