aboutsummaryrefslogtreecommitdiffhomepage
path: root/php
diff options
context:
space:
mode:
authorGravatar Jisi Liu <jisi.liu@gmail.com>2018-01-03 09:28:40 -0800
committerGravatar Jisi Liu <jisi.liu@gmail.com>2018-01-03 09:28:40 -0800
commit383a4941d5b1aa3c0afbdc24dd0e5d63d263fc3a (patch)
tree45bdce007f64e47ff2a0b60fb1920efc3eaf3b00 /php
parent8529f2aee33ae793c9ce362a45370b98f675370a (diff)
parent88e5573b9a8a5c4038f9db3633610f032aab277d (diff)
Merge remote-tracking branch 'origin/3.5.x' into master
Diffstat (limited to 'php')
-rw-r--r--php/ext/google/protobuf/def.c2
-rw-r--r--php/ext/google/protobuf/encode_decode.c95
-rw-r--r--php/ext/google/protobuf/message.c79
-rw-r--r--php/ext/google/protobuf/package.xml38
-rw-r--r--php/ext/google/protobuf/protobuf.c9
-rw-r--r--php/ext/google/protobuf/protobuf.h6
-rw-r--r--php/ext/google/protobuf/type_check.c7
-rw-r--r--php/src/Google/Protobuf/Internal/Message.php30
-rw-r--r--php/tests/encode_decode_test.php40
-rw-r--r--php/tests/memory_leak_test.php44
10 files changed, 320 insertions, 30 deletions
diff --git a/php/ext/google/protobuf/def.c b/php/ext/google/protobuf/def.c
index 13f7cdd6..8140fe47 100644
--- a/php/ext/google/protobuf/def.c
+++ b/php/ext/google/protobuf/def.c
@@ -249,9 +249,11 @@ PHP_METHOD(Descriptor, getField) {
MAKE_STD_ZVAL(field_hashtable_value);
ZVAL_OBJ(field_hashtable_value, field_descriptor_type->create_object(
field_descriptor_type TSRMLS_CC));
+ Z_DELREF_P(field_hashtable_value);
#else
field_hashtable_value =
field_descriptor_type->create_object(field_descriptor_type TSRMLS_CC);
+ --GC_REFCOUNT(field_hashtable_value);
#endif
FieldDescriptor *field_php =
UNBOX_HASHTABLE_VALUE(FieldDescriptor, field_hashtable_value);
diff --git a/php/ext/google/protobuf/encode_decode.c b/php/ext/google/protobuf/encode_decode.c
index ae5a61f5..b98121bb 100644
--- a/php/ext/google/protobuf/encode_decode.c
+++ b/php/ext/google/protobuf/encode_decode.c
@@ -1402,7 +1402,6 @@ static void putarray(zval* array, const upb_fielddef* f, upb_sink* sink,
RepeatedField* intern = UNBOX(RepeatedField, array);
HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
size = zend_hash_num_elements(ht);
- // size = zend_hash_num_elements(PHP_PROTO_HASH_OF(intern->array));
if (size == 0) return;
upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
@@ -1615,11 +1614,101 @@ PHP_METHOD(Message, mergeFromJsonString) {
}
}
-PHP_METHOD(Message, discardUnknownFields) {
- MessageHeader* msg = UNBOX(MessageHeader, getThis());
+// TODO(teboring): refactoring with putrawmsg
+static void discard_unknown_fields(MessageHeader* msg) {
+ upb_msg_field_iter it;
+
stringsink* unknown = DEREF(message_data(msg), 0, stringsink*);
if (unknown != NULL) {
stringsink_uninit(unknown);
DEREF(message_data(msg), 0, stringsink*) = NULL;
}
+
+ // Recursively discard unknown fields of submessages.
+ Descriptor* desc = msg->descriptor;
+ TSRMLS_FETCH();
+ for (upb_msg_field_begin(&it, desc->msgdef);
+ !upb_msg_field_done(&it);
+ upb_msg_field_next(&it)) {
+ upb_fielddef* f = upb_msg_iter_field(&it);
+ uint32_t offset = desc->layout->fields[upb_fielddef_index(f)].offset;
+ bool containing_oneof = false;
+
+ if (upb_fielddef_containingoneof(f)) {
+ uint32_t oneof_case_offset =
+ desc->layout->fields[upb_fielddef_index(f)].case_offset;
+ // For a oneof, check that this field is actually present -- skip all the
+ // below if not.
+ if (DEREF(message_data(msg), oneof_case_offset, uint32_t) !=
+ upb_fielddef_number(f)) {
+ continue;
+ }
+ // Otherwise, fall through to the appropriate singular-field handler
+ // below.
+ containing_oneof = true;
+ }
+
+ if (is_map_field(f)) {
+ MapIter map_it;
+ int len, size;
+ const upb_fielddef* value_field;
+
+ value_field = map_field_value(f);
+ if (!upb_fielddef_issubmsg(value_field)) continue;
+
+ zval* map_php = CACHED_PTR_TO_ZVAL_PTR(
+ DEREF(message_data(msg), offset, CACHED_VALUE*));
+ if (map_php == NULL) continue;
+
+ Map* intern = UNBOX(Map, map_php);
+ for (map_begin(map_php, &map_it TSRMLS_CC);
+ !map_done(&map_it); map_next(&map_it)) {
+ upb_value value = map_iter_value(&map_it, &len);
+ void* memory = raw_value(upb_value_memory(&value), value_field);
+#if PHP_MAJOR_VERSION < 7
+ MessageHeader *submsg = UNBOX(MessageHeader, *(zval**)memory);
+#else
+ MessageHeader *submsg =
+ (MessageHeader*)((char*)(Z_OBJ_P((zval*)memory)) -
+ XtOffsetOf(MessageHeader, std));
+#endif
+ discard_unknown_fields(submsg);
+ }
+ } else if (upb_fielddef_isseq(f)) {
+ if (!upb_fielddef_issubmsg(f)) continue;
+
+ zval* array_php = CACHED_PTR_TO_ZVAL_PTR(
+ DEREF(message_data(msg), offset, CACHED_VALUE*));
+ if (array_php == NULL) continue;
+
+ int size, i;
+ RepeatedField* intern = UNBOX(RepeatedField, array_php);
+ HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
+ size = zend_hash_num_elements(ht);
+ if (size == 0) continue;
+
+ for (i = 0; i < size; i++) {
+ void* memory = repeated_field_index_native(intern, i TSRMLS_CC);
+#if PHP_MAJOR_VERSION < 7
+ MessageHeader *submsg = UNBOX(MessageHeader, *(zval**)memory);
+#else
+ MessageHeader *submsg =
+ (MessageHeader*)((char*)(Z_OBJ_P((zval*)memory)) -
+ XtOffsetOf(MessageHeader, std));
+#endif
+ discard_unknown_fields(submsg);
+ }
+ } else if (upb_fielddef_issubmsg(f)) {
+ zval* submsg_php = CACHED_PTR_TO_ZVAL_PTR(
+ DEREF(message_data(msg), offset, CACHED_VALUE*));
+ if (Z_TYPE_P(submsg_php) == IS_NULL) continue;
+ MessageHeader* submsg = UNBOX(MessageHeader, submsg_php);
+ discard_unknown_fields(submsg);
+ }
+ }
+}
+
+PHP_METHOD(Message, discardUnknownFields) {
+ MessageHeader* msg = UNBOX(MessageHeader, getThis());
+ discard_unknown_fields(msg);
}
diff --git a/php/ext/google/protobuf/message.c b/php/ext/google/protobuf/message.c
index 6db010c5..24472682 100644
--- a/php/ext/google/protobuf/message.c
+++ b/php/ext/google/protobuf/message.c
@@ -29,7 +29,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <php.h>
-#include <ext/date/php_date.h>
#include <stdlib.h>
#include "protobuf.h"
@@ -379,6 +378,7 @@ PHP_METHOD(Message, whichOneof) {
PHP_PROTO_FAKE_SCOPE_BEGIN(LOWER_CLASS##_type); \
zval* value = message_get_property_internal(getThis(), &member TSRMLS_CC); \
PHP_PROTO_FAKE_SCOPE_END; \
+ zval_dtor(&member); \
PHP_PROTO_RETVAL_ZVAL(value); \
} \
PHP_METHOD(UPPER_CLASS, set##UPPER_FIELD) { \
@@ -390,6 +390,7 @@ PHP_METHOD(Message, whichOneof) {
zval member; \
PHP_PROTO_ZVAL_STRING(&member, LOWER_FIELD, 1); \
message_set_property_internal(getThis(), &member, value TSRMLS_CC); \
+ zval_dtor(&member); \
PHP_PROTO_RETVAL_ZVAL(getThis()); \
}
@@ -402,6 +403,7 @@ PHP_METHOD(Message, whichOneof) {
message_get_oneof_property_internal(getThis(), &member, \
return_value TSRMLS_CC); \
PHP_PROTO_FAKE_SCOPE_END; \
+ zval_dtor(&member); \
} \
PHP_METHOD(UPPER_CLASS, set##UPPER_FIELD) { \
zval* value = NULL; \
@@ -412,6 +414,7 @@ PHP_METHOD(Message, whichOneof) {
zval member; \
PHP_PROTO_ZVAL_STRING(&member, LOWER_FIELD, 1); \
message_set_property_internal(getThis(), &member, value TSRMLS_CC); \
+ zval_dtor(&member); \
PHP_PROTO_RETVAL_ZVAL(getThis()); \
}
@@ -1120,17 +1123,41 @@ PHP_METHOD(Timestamp, fromDateTime) {
zval* datetime;
zval member;
+ PHP_PROTO_CE_DECLARE date_interface_ce;
+ if (php_proto_zend_lookup_class("\\DatetimeInterface", 18,
+ &date_interface_ce) == FAILURE) {
+ zend_error(E_ERROR, "Make sure date extension is enabled.");
+ return;
+ }
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &datetime,
- php_date_get_date_ce()) == FAILURE) {
+ PHP_PROTO_CE_UNREF(date_interface_ce)) == FAILURE) {
+ zend_error(E_USER_ERROR, "Expect DatetimeInterface.");
return;
}
- php_date_obj* dateobj = UNBOX(php_date_obj, datetime);
- if (!dateobj->time->sse_uptodate) {
- timelib_update_ts(dateobj->time, NULL);
+ // Get timestamp from Datetime object.
+ zval retval;
+ zval function_name;
+ int64_t timestamp;
+
+#if PHP_MAJOR_VERSION < 7
+ INIT_ZVAL(retval);
+ INIT_ZVAL(function_name);
+#endif
+
+ PHP_PROTO_ZVAL_STRING(&function_name, "date_timestamp_get", 1);
+
+ if (call_user_function(EG(function_table), NULL, &function_name, &retval, 1,
+ ZVAL_PTR_TO_CACHED_PTR(datetime) TSRMLS_CC) == FAILURE) {
+ zend_error(E_ERROR, "Cannot get timestamp from DateTime.");
+ return;
}
- int64_t timestamp = dateobj->time->sse;
+ protobuf_convert_to_int64(&retval, &timestamp);
+
+ zval_dtor(&retval);
+ zval_dtor(&function_name);
// Set seconds
MessageHeader* self = UNBOX(MessageHeader, getThis());
@@ -1138,20 +1165,18 @@ PHP_METHOD(Timestamp, fromDateTime) {
upb_msgdef_ntofz(self->descriptor->msgdef, "seconds");
void* storage = message_data(self);
void* memory = slot_memory(self->descriptor->layout, storage, field);
- *(int64_t*)memory = dateobj->time->sse;
+ *(int64_t*)memory = timestamp;
// Set nanos
field = upb_msgdef_ntofz(self->descriptor->msgdef, "nanos");
storage = message_data(self);
memory = slot_memory(self->descriptor->layout, storage, field);
*(int32_t*)memory = 0;
+
+ RETURN_NULL();
}
PHP_METHOD(Timestamp, toDateTime) {
- zval datetime;
- php_date_instantiate(php_date_get_date_ce(), &datetime TSRMLS_CC);
- php_date_obj* dateobj = UNBOX(php_date_obj, &datetime);
-
// Get seconds
MessageHeader* self = UNBOX(MessageHeader, getThis());
const upb_fielddef* field =
@@ -1172,14 +1197,38 @@ PHP_METHOD(Timestamp, toDateTime) {
strftime(formated_time, sizeof(formated_time), "%Y-%m-%dT%H:%M:%SUTC",
utc_time);
- if (!php_date_initialize(dateobj, formated_time, strlen(formated_time), NULL,
- NULL, 0 TSRMLS_CC)) {
- zval_dtor(&datetime);
- RETURN_NULL();
+ // Create Datetime object.
+ zval datetime;
+ zval formated_time_php;
+ zval function_name;
+ int64_t timestamp = 0;
+
+#if PHP_MAJOR_VERSION < 7
+ INIT_ZVAL(function_name);
+ INIT_ZVAL(formated_time_php);
+#endif
+
+ PHP_PROTO_ZVAL_STRING(&function_name, "date_create", 1);
+ PHP_PROTO_ZVAL_STRING(&formated_time_php, formated_time, 1);
+
+ CACHED_VALUE params[1] = {ZVAL_TO_CACHED_VALUE(formated_time_php)};
+
+ if (call_user_function(EG(function_table), NULL,
+ &function_name, &datetime, 1,
+ params TSRMLS_CC) == FAILURE) {
+ zend_error(E_ERROR, "Cannot create DateTime.");
+ return;
}
+ zval_dtor(&formated_time_php);
+ zval_dtor(&function_name);
+
+#if PHP_MAJOR_VERSION < 7
zval* datetime_ptr = &datetime;
PHP_PROTO_RETVAL_ZVAL(datetime_ptr);
+#else
+ ZVAL_OBJ(return_value, Z_OBJ(datetime));
+#endif
}
// -----------------------------------------------------------------------------
diff --git a/php/ext/google/protobuf/package.xml b/php/ext/google/protobuf/package.xml
index 53aa4c7f..626eb46b 100644
--- a/php/ext/google/protobuf/package.xml
+++ b/php/ext/google/protobuf/package.xml
@@ -10,11 +10,11 @@
<email>protobuf-opensource@google.com</email>
<active>yes</active>
</lead>
- <date>2017-11-15</date>
+ <date>2017-12-11</date>
<time>11:02:07</time>
<version>
- <release>3.5.0</release>
- <api>3.5.0</api>
+ <release>3.5.1</release>
+ <api>3.5.1</api>
</version>
<stability>
<release>stable</release>
@@ -184,5 +184,37 @@ GA release.
GA release.
</notes>
</release>
+ <release>
+ <version>
+ <release>3.5.0.1</release>
+ <api>3.5.0.1</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <date>2017-12-06</date>
+ <time>11:02:07</time>
+ <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+ <notes>
+GA release.
+ </notes>
+ </release>
+ <release>
+ <version>
+ <release>3.5.1</release>
+ <api>3.5.1</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <date>2017-12-11</date>
+ <time>11:02:07</time>
+ <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+ <notes>
+GA release.
+ </notes>
+ </release>
</changelog>
</package>
diff --git a/php/ext/google/protobuf/protobuf.c b/php/ext/google/protobuf/protobuf.c
index 265d636e..daebb460 100644
--- a/php/ext/google/protobuf/protobuf.c
+++ b/php/ext/google/protobuf/protobuf.c
@@ -182,8 +182,15 @@ zend_function_entry protobuf_functions[] = {
ZEND_FE_END
};
+static const zend_module_dep protobuf_deps[] = {
+ ZEND_MOD_OPTIONAL("date")
+ ZEND_MOD_END
+};
+
zend_module_entry protobuf_module_entry = {
- STANDARD_MODULE_HEADER,
+ STANDARD_MODULE_HEADER_EX,
+ NULL,
+ protobuf_deps,
PHP_PROTOBUF_EXTNAME, // extension name
protobuf_functions, // function list
PHP_MINIT(protobuf), // process startup
diff --git a/php/ext/google/protobuf/protobuf.h b/php/ext/google/protobuf/protobuf.h
index bd475144..6ab0f134 100644
--- a/php/ext/google/protobuf/protobuf.h
+++ b/php/ext/google/protobuf/protobuf.h
@@ -37,7 +37,7 @@
#include "upb.h"
#define PHP_PROTOBUF_EXTNAME "protobuf"
-#define PHP_PROTOBUF_VERSION "3.5.0"
+#define PHP_PROTOBUF_VERSION "3.5.1"
#define MAX_LENGTH_OF_INT64 20
#define SIZEOF_INT64 8
@@ -182,6 +182,8 @@
#define CACHED_TO_ZVAL_PTR(VALUE) (VALUE)
#define CACHED_PTR_TO_ZVAL_PTR(VALUE) (*VALUE)
#define ZVAL_PTR_TO_CACHED_PTR(VALUE) (&VALUE)
+#define ZVAL_PTR_TO_CACHED_VALUE(VALUE) (VALUE)
+#define ZVAL_TO_CACHED_VALUE(VALUE) (&VALUE)
#define CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(zval_ptr, class_type) \
ZVAL_OBJ(zval_ptr, class_type->create_object(class_type TSRMLS_CC));
@@ -452,6 +454,8 @@ static inline int php_proto_zend_hash_get_current_data_ex(HashTable* ht,
#define CACHED_TO_ZVAL_PTR(VALUE) (&VALUE)
#define CACHED_PTR_TO_ZVAL_PTR(VALUE) (VALUE)
#define ZVAL_PTR_TO_CACHED_PTR(VALUE) (VALUE)
+#define ZVAL_PTR_TO_CACHED_VALUE(VALUE) (*VALUE)
+#define ZVAL_TO_CACHED_VALUE(VALUE) (VALUE)
#define CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(zval_ptr, class_type) \
ZVAL_OBJ(zval_ptr, class_type->create_object(class_type));
diff --git a/php/ext/google/protobuf/type_check.c b/php/ext/google/protobuf/type_check.c
index f588774c..85f5051e 100644
--- a/php/ext/google/protobuf/type_check.c
+++ b/php/ext/google/protobuf/type_check.c
@@ -461,8 +461,7 @@ void check_repeated_field(const zend_class_entry* klass, PHP_PROTO_LONG type,
CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory) TSRMLS_CC);
}
- Z_DELREF_P(CACHED_TO_ZVAL_PTR(repeated_field));
- RETURN_ZVAL(CACHED_TO_ZVAL_PTR(repeated_field), 1, 0);
+ RETURN_ZVAL(CACHED_TO_ZVAL_PTR(repeated_field), 1, 1);
} else if (Z_TYPE_P(val) == IS_OBJECT) {
if (!instanceof_function(Z_OBJCE_P(val), repeated_field_type TSRMLS_CC)) {
@@ -533,10 +532,10 @@ void check_map_field(const zend_class_entry* klass, PHP_PROTO_LONG key_type,
map_field_handlers->write_dimension(
CACHED_TO_ZVAL_PTR(map_field), &key,
CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)value) TSRMLS_CC);
+ zval_dtor(&key);
}
- Z_DELREF_P(CACHED_TO_ZVAL_PTR(map_field));
- RETURN_ZVAL(CACHED_TO_ZVAL_PTR(map_field), 1, 0);
+ RETURN_ZVAL(CACHED_TO_ZVAL_PTR(map_field), 1, 1);
} else if (Z_TYPE_P(val) == IS_OBJECT) {
if (!instanceof_function(Z_OBJCE_P(val), map_field_type TSRMLS_CC)) {
zend_error(E_USER_ERROR, "Given value is not an instance of %s.",
diff --git a/php/src/Google/Protobuf/Internal/Message.php b/php/src/Google/Protobuf/Internal/Message.php
index 26d20575..b7f83c57 100644
--- a/php/src/Google/Protobuf/Internal/Message.php
+++ b/php/src/Google/Protobuf/Internal/Message.php
@@ -583,6 +583,34 @@ class Message
public function discardUnknownFields()
{
$this->unknown = "";
+ foreach ($this->desc->getField() as $field) {
+ if ($field->getType() != GPBType::MESSAGE) {
+ continue;
+ }
+ if ($field->isMap()) {
+ $value_field = $field->getMessageType()->getFieldByNumber(2);
+ if ($value_field->getType() != GPBType::MESSAGE) {
+ continue;
+ }
+ $getter = $field->getGetter();
+ $map = $this->$getter();
+ foreach ($map as $key => $value) {
+ $value->discardUnknownFields();
+ }
+ } else if ($field->getLabel() === GPBLabel::REPEATED) {
+ $getter = $field->getGetter();
+ $arr = $this->$getter();
+ foreach ($arr as $sub) {
+ $sub->discardUnknownFields();
+ }
+ } else if ($field->getLabel() === GPBLabel::OPTIONAL) {
+ $getter = $field->getGetter();
+ $sub = $this->$getter();
+ if (!is_null($sub)) {
+ $sub->discardUnknownFields();
+ }
+ }
+ }
}
/**
@@ -1083,7 +1111,7 @@ class Message
}
try {
$this->mergeFromJsonArray($array);
- } catch (Exception $e) {
+ } catch (\Exception $e) {
throw new GPBDecodeException($e->getMessage());
}
}
diff --git a/php/tests/encode_decode_test.php b/php/tests/encode_decode_test.php
index 4512c871..74d5526d 100644
--- a/php/tests/encode_decode_test.php
+++ b/php/tests/encode_decode_test.php
@@ -443,36 +443,74 @@ class EncodeDecodeTest extends TestBase
public function testUnknown()
{
+ // Test preserve unknown for varint.
$m = new TestMessage();
- $from = hex2bin('F80601');
+ $from = hex2bin('F80601'); // TODO(teboring): Add a util to encode
+ // varint for better readability
$m->mergeFromString($from);
$to = $m->serializeToString();
$this->assertSame(bin2hex($from), bin2hex($to));
+ // Test preserve unknown for 64-bit.
$m = new TestMessage();
$from = hex2bin('F9060000000000000000');
$m->mergeFromString($from);
$to = $m->serializeToString();
$this->assertSame(bin2hex($from), bin2hex($to));
+ // Test preserve unknown for length delimited.
$m = new TestMessage();
$from = hex2bin('FA0600');
$m->mergeFromString($from);
$to = $m->serializeToString();
$this->assertSame(bin2hex($from), bin2hex($to));
+ // Test preserve unknown for 32-bit.
$m = new TestMessage();
$from = hex2bin('FD0600000000');
$m->mergeFromString($from);
$to = $m->serializeToString();
$this->assertSame(bin2hex($from), bin2hex($to));
+ // Test discard unknown in message.
$m = new TestMessage();
$from = hex2bin('F80601');
$m->mergeFromString($from);
$m->discardUnknownFields();
$to = $m->serializeToString();
$this->assertSame("", bin2hex($to));
+
+ // Test discard unknown for singular message field.
+ $m = new TestMessage();
+ $from = hex2bin('8A0103F80601');
+ $m->mergeFromString($from);
+ $m->discardUnknownFields();
+ $to = $m->serializeToString();
+ $this->assertSame("8a0100", bin2hex($to));
+
+ // Test discard unknown for repeated message field.
+ $m = new TestMessage();
+ $from = hex2bin('FA0203F80601');
+ $m->mergeFromString($from);
+ $m->discardUnknownFields();
+ $to = $m->serializeToString();
+ $this->assertSame("fa0200", bin2hex($to));
+
+ // Test discard unknown for map message value field.
+ $m = new TestMessage();
+ $from = hex2bin("BA050708011203F80601");
+ $m->mergeFromString($from);
+ $m->discardUnknownFields();
+ $to = $m->serializeToString();
+ $this->assertSame("ba050408011200", bin2hex($to));
+
+ // Test discard unknown for singular message field.
+ $m = new TestMessage();
+ $from = hex2bin('9A0403F80601');
+ $m->mergeFromString($from);
+ $m->discardUnknownFields();
+ $to = $m->serializeToString();
+ $this->assertSame("9a0400", bin2hex($to));
}
public function testJsonEncode()
diff --git a/php/tests/memory_leak_test.php b/php/tests/memory_leak_test.php
index b76c8bff..507635e7 100644
--- a/php/tests/memory_leak_test.php
+++ b/php/tests/memory_leak_test.php
@@ -50,7 +50,8 @@ $to->mergeFromString($data);
TestUtil::assertTestMessage($to);
-$from->setRecursive($from);
+// TODO(teboring): This causes following tests fail in php7.
+# $from->setRecursive($from);
$arr = new RepeatedField(GPBType::MESSAGE, TestMessage::class);
$arr[] = new TestMessage;
@@ -105,6 +106,47 @@ $m = new TestMessage();
$m->mergeFromString(hex2bin('F80601'));
assert('F80601', bin2hex($m->serializeToString()));
+// Test create repeated field via array.
+$str_arr = array("abc");
+$m = new TestMessage();
+$m->setRepeatedString($str_arr);
+
+// Test create map field via array.
+$str_arr = array("abc"=>"abc");
+$m = new TestMessage();
+$m->setMapStringString($str_arr);
+
+// Test unset
+$from = new TestMessage();
+TestUtil::setTestMessage($from);
+unset($from);
+
+// Test wellknown
+$from = new \Google\Protobuf\Timestamp();
+$from->setSeconds(1);
+assert(1, $from->getSeconds());
+
+$timestamp = new \Google\Protobuf\Timestamp();
+
+date_default_timezone_set('UTC');
+$from = new DateTime('2011-01-01T15:03:01.012345UTC');
+$timestamp->fromDateTime($from);
+assert($from->format('U') == $timestamp->getSeconds());
+assert(0 == $timestamp->getNanos());
+
+$to = $timestamp->toDateTime();
+assert(\DateTime::class == get_class($to));
+assert($from->format('U') == $to->format('U'));
+
+$from = new \Google\Protobuf\Value();
+$from->setNumberValue(1);
+assert(1, $from->getNumberValue());
+
+// Test descriptor
+$pool = \Google\Protobuf\DescriptorPool::getGeneratedPool();
+$desc = $pool->getDescriptorByClassName("\Foo\TestMessage");
+$field = $desc->getField(1);
+
# $from = new TestMessage();
# $to = new TestMessage();
# TestUtil::setTestMessage($from);