Commit c7457ef6 authored by Paul Yang's avatar Paul Yang Committed by GitHub

Add any support in php runtime. (#3486)

* Add any support in php runtime.

* Remove unused file in config.m4

* Fix comments

* Fix error for tsrmls build

* Add newly added file to Makefile.am
parent 98a3734b
......@@ -600,6 +600,7 @@ php_EXTRA_DIST= \
php/ext/google/protobuf/upb.c \
php/ext/google/protobuf/protobuf.c \
php/src/phpdoc.dist.xml \
php/src/Google/Protobuf/Any.php \
php/src/Google/Protobuf/Descriptor.php \
php/src/Google/Protobuf/DescriptorPool.php \
php/src/Google/Protobuf/EnumDescriptor.php \
......@@ -664,6 +665,7 @@ php_EXTRA_DIST= \
php/src/Google/Protobuf/Internal/SourceCodeInfo.php \
php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php \
php/src/Google/Protobuf/Internal/UninterpretedOption.php \
php/src/GPBMetadata/Google/Protobuf/Any.php \
php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php \
php/tests/array_test.php \
php/tests/autoload.php \
......
......@@ -115,33 +115,6 @@ static void append_map_entry_name(char *result, const char *field_name,
check_upb_status(&status, msg); \
} while (0)
// Define PHP class
#define DEFINE_PROTOBUF_INIT_CLASS(CLASSNAME, CAMELNAME, LOWERNAME) \
PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWERNAME) \
PHP_PROTO_INIT_CLASS_END
#define DEFINE_PROTOBUF_CREATE(NAME, LOWERNAME) \
PHP_PROTO_OBJECT_CREATE_START(NAME, LOWERNAME) \
LOWERNAME##_init_c_instance(intern TSRMLS_CC); \
PHP_PROTO_OBJECT_CREATE_END(NAME, LOWERNAME)
#define DEFINE_PROTOBUF_FREE(CAMELNAME, LOWERNAME) \
PHP_PROTO_OBJECT_FREE_START(CAMELNAME, LOWERNAME) \
LOWERNAME##_free_c(intern TSRMLS_CC); \
PHP_PROTO_OBJECT_FREE_END
#define DEFINE_PROTOBUF_DTOR(CAMELNAME, LOWERNAME) \
PHP_PROTO_OBJECT_DTOR_START(CAMELNAME, LOWERNAME) \
PHP_PROTO_OBJECT_DTOR_END
#define DEFINE_CLASS(NAME, LOWERNAME, string_name) \
zend_class_entry *LOWERNAME##_type; \
zend_object_handlers *LOWERNAME##_handlers; \
DEFINE_PROTOBUF_FREE(NAME, LOWERNAME) \
DEFINE_PROTOBUF_DTOR(NAME, LOWERNAME) \
DEFINE_PROTOBUF_CREATE(NAME, LOWERNAME) \
DEFINE_PROTOBUF_INIT_CLASS(string_name, NAME, LOWERNAME)
// -----------------------------------------------------------------------------
// GPBType
// -----------------------------------------------------------------------------
......@@ -657,7 +630,7 @@ zend_object *internal_generated_pool_php;
#endif
InternalDescriptorPool *generated_pool; // The actual generated pool
static void init_generated_pool_once(TSRMLS_D) {
void init_generated_pool_once(TSRMLS_D) {
if (generated_pool == NULL) {
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL(generated_pool_php);
......@@ -843,18 +816,11 @@ static void convert_to_class_name_inplace(const char *package,
memcpy(classname + i, prefix, prefix_len);
}
PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile) {
char *data = NULL;
PHP_PROTO_SIZE data_len;
void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len,
InternalDescriptorPool *pool TSRMLS_DC) {
upb_filedef **files;
size_t i;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) ==
FAILURE) {
return;
}
InternalDescriptorPool *pool = UNBOX(InternalDescriptorPool, getThis());
CHECK_UPB(files = upb_loaddescriptor(data, data_len, &pool, &status),
"Parse binary descriptors to internal descriptors failed");
......@@ -913,6 +879,8 @@ PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile) {
desc->klass = PHP_PROTO_CE_UNREF(pce); \
} \
add_ce_obj(desc->klass, desc_php); \
add_proto_obj(upb_##def_type_lower##_fullname(desc->def_type_lower), \
desc_php); \
efree(classname); \
break; \
}
......@@ -939,6 +907,21 @@ PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile) {
upb_gfree(files);
}
PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile) {
char *data = NULL;
PHP_PROTO_SIZE data_len;
upb_filedef **files;
size_t i;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) ==
FAILURE) {
return;
}
InternalDescriptorPool *pool = UNBOX(InternalDescriptorPool, getThis());
internal_add_generated_file(data, data_len, pool TSRMLS_CC);
}
PHP_METHOD(DescriptorPool, getDescriptorByClassName) {
DescriptorPool *public_pool = UNBOX(DescriptorPool, getThis());
InternalDescriptorPool *pool = public_pool->intern;
......
......@@ -1445,9 +1445,9 @@ static const upb_handlers* msgdef_json_serialize_handlers(
// PHP encode/decode methods
// -----------------------------------------------------------------------------
PHP_METHOD(Message, serializeToString) {
void serialize_to_string(zval* val, zval* return_value TSRMLS_DC) {
Descriptor* desc =
UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(getThis())));
UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(val)));
stringsink sink;
stringsink_init(&sink);
......@@ -1461,7 +1461,7 @@ PHP_METHOD(Message, serializeToString) {
stackenv_init(&se, "Error occurred during encoding: %s");
encoder = upb_pb_encoder_create(&se.env, serialize_handlers, &sink.sink);
putmsg(getThis(), desc, upb_pb_encoder_input(encoder), 0 TSRMLS_CC);
putmsg(val, desc, upb_pb_encoder_input(encoder), 0 TSRMLS_CC);
PHP_PROTO_RETVAL_STRINGL(sink.ptr, sink.len, 1);
......@@ -1470,6 +1470,26 @@ PHP_METHOD(Message, serializeToString) {
}
}
PHP_METHOD(Message, serializeToString) {
serialize_to_string(getThis(), return_value TSRMLS_CC);
}
void merge_from_string(const char* data, int data_len, const Descriptor* desc,
MessageHeader* msg) {
const upb_pbdecodermethod* method = msgdef_decodermethod(desc);
const upb_handlers* h = upb_pbdecodermethod_desthandlers(method);
stackenv se;
upb_sink sink;
upb_pbdecoder* decoder;
stackenv_init(&se, "Error occurred during parsing: %s");
upb_sink_reset(&sink, h, msg);
decoder = upb_pbdecoder_create(&se.env, method, &sink);
upb_bufsrc_putbuf(data, data_len, upb_pbdecoder_input(decoder));
stackenv_uninit(&se);
}
PHP_METHOD(Message, mergeFromString) {
Descriptor* desc =
UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(getThis())));
......@@ -1483,20 +1503,7 @@ PHP_METHOD(Message, mergeFromString) {
return;
}
{
const upb_pbdecodermethod* method = msgdef_decodermethod(desc);
const upb_handlers* h = upb_pbdecodermethod_desthandlers(method);
stackenv se;
upb_sink sink;
upb_pbdecoder* decoder;
stackenv_init(&se, "Error occurred during parsing: %s");
upb_sink_reset(&sink, h, msg);
decoder = upb_pbdecoder_create(&se.env, method, &sink);
upb_bufsrc_putbuf(data, data_len, upb_pbdecoder_input(decoder));
stackenv_uninit(&se);
}
merge_from_string(data, data_len, desc, msg);
}
PHP_METHOD(Message, serializeToJsonString) {
......
......@@ -32,9 +32,11 @@
#include <stdlib.h>
#include "protobuf.h"
#include "utf8.h"
static zend_class_entry* message_type;
zend_class_entry* message_type;
zend_object_handlers* message_handlers;
static const char TYPE_URL_PREFIX[] = "type.googleapis.com/";
static zend_function_entry message_methods[] = {
PHP_ME(Message, clear, NULL, ZEND_ACC_PUBLIC)
......@@ -342,3 +344,276 @@ PHP_METHOD(Message, whichOneof) {
msg->descriptor->layout, message_data(msg), oneof TSRMLS_CC);
PHP_PROTO_RETURN_STRING(oneof_case_name, 1);
}
// -----------------------------------------------------------------------------
// Any
// -----------------------------------------------------------------------------
static zend_function_entry any_methods[] = {
PHP_ME(Any, __construct, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Any, getTypeUrl, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Any, setTypeUrl, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Any, getValue, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Any, setValue, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Any, pack, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Any, unpack, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Any, is, NULL, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
zend_class_entry* any_type;
// Init class entry.
PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Any", Any, any)
zend_class_implements(any_type TSRMLS_CC, 1, message_type);
zend_declare_property_string(any_type, "type_url", strlen("type_url"),
"" ,ZEND_ACC_PRIVATE TSRMLS_CC);
zend_declare_property_string(any_type, "value", strlen("value"),
"" ,ZEND_ACC_PRIVATE TSRMLS_CC);
PHP_PROTO_INIT_SUBMSGCLASS_END
void hex_to_binary(const char* hex, char** binary, int* binary_len) {
int i;
int hex_len = strlen(hex);
*binary_len = hex_len / 2;
*binary = ALLOC_N(char, *binary_len);
for (i = 0; i < *binary_len; i++) {
char value = 0;
if (hex[i * 2] >= '0' && hex[i * 2] <= '9') {
value += (hex[i * 2] - '0') * 16;
} else {
value += (hex[i * 2] - 'a' + 10) * 16;
}
if (hex[i * 2 + 1] >= '0' && hex[i * 2 + 1] <= '9') {
value += hex[i * 2 + 1] - '0';
} else {
value += hex[i * 2 + 1] - 'a' + 10;
}
(*binary)[i] = value;
}
}
PHP_METHOD(Any, __construct) {
PHP_PROTO_HASHTABLE_VALUE desc_php = get_ce_obj(any_type);
if (desc_php == NULL) {
init_generated_pool_once(TSRMLS_C);
const char* generated_file =
"0acd010a19676f6f676c652f70726f746f6275662f616e792e70726f746f"
"120f676f6f676c652e70726f746f62756622260a03416e7912100a087479"
"70655f75726c180120012809120d0a0576616c756518022001280c426f0a"
"13636f6d2e676f6f676c652e70726f746f6275664208416e7950726f746f"
"50015a256769746875622e636f6d2f676f6c616e672f70726f746f627566"
"2f7074797065732f616e79a20203475042aa021e476f6f676c652e50726f"
"746f6275662e57656c6c4b6e6f776e5479706573620670726f746f33";
char* binary;
int binary_len;
hex_to_binary(generated_file, &binary, &binary_len);
internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
FREE(binary);
}
MessageHeader* intern = UNBOX(MessageHeader, getThis());
custom_data_init(any_type, intern PHP_PROTO_TSRMLS_CC);
}
PHP_METHOD(Any, getTypeUrl) {
zval member;
PHP_PROTO_ZVAL_STRING(&member, "type_url", 1);
PHP_PROTO_FAKE_SCOPE_BEGIN(any_type);
#if PHP_MAJOR_VERSION < 7
zval* value = message_handlers->read_property(getThis(), &member, BP_VAR_R,
NULL PHP_PROTO_TSRMLS_CC);
#else
zval* value = message_handlers->read_property(getThis(), &member, BP_VAR_R,
NULL, NULL PHP_PROTO_TSRMLS_CC);
#endif
PHP_PROTO_FAKE_SCOPE_END;
PHP_PROTO_RETVAL_ZVAL(value);
}
PHP_METHOD(Any, setTypeUrl) {
char *type_url = NULL;
PHP_PROTO_SIZE type_url_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &type_url,
&type_url_len) == FAILURE) {
return;
}
zval member;
zval value;
PHP_PROTO_ZVAL_STRING(&member, "type_url", 1);
PHP_PROTO_ZVAL_STRINGL(&value, type_url, type_url_len, 1);
PHP_PROTO_FAKE_SCOPE_BEGIN(any_type);
message_handlers->write_property(getThis(), &member, &value,
NULL PHP_PROTO_TSRMLS_CC);
PHP_PROTO_FAKE_SCOPE_END;
PHP_PROTO_RETVAL_ZVAL(getThis());
}
PHP_METHOD(Any, getValue) {
zval member;
PHP_PROTO_ZVAL_STRING(&member, "value", 1);
PHP_PROTO_FAKE_SCOPE_BEGIN(any_type);
zval* value =
php_proto_message_read_property(getThis(), &member PHP_PROTO_TSRMLS_CC);
PHP_PROTO_FAKE_SCOPE_END;
PHP_PROTO_RETVAL_ZVAL(value);
}
PHP_METHOD(Any, setValue) {
char *value = NULL;
PHP_PROTO_SIZE value_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &value,
&value_len) == FAILURE) {
return;
}
zval member;
zval value_to_set;
PHP_PROTO_ZVAL_STRING(&member, "value", 1);
PHP_PROTO_ZVAL_STRINGL(&value_to_set, value, value_len, 1);
PHP_PROTO_FAKE_SCOPE_BEGIN(any_type);
message_handlers->write_property(getThis(), &member, &value_to_set,
NULL PHP_PROTO_TSRMLS_CC);
PHP_PROTO_FAKE_SCOPE_END;
PHP_PROTO_RETVAL_ZVAL(getThis());
}
PHP_METHOD(Any, unpack) {
// Get type url.
zval type_url_member;
PHP_PROTO_ZVAL_STRING(&type_url_member, "type_url", 1);
PHP_PROTO_FAKE_SCOPE_BEGIN(any_type);
zval* type_url_php = php_proto_message_read_property(
getThis(), &type_url_member PHP_PROTO_TSRMLS_CC);
PHP_PROTO_FAKE_SCOPE_END;
// Get fully-qualified name from type url.
size_t url_prefix_len = strlen(TYPE_URL_PREFIX);
const char* type_url = Z_STRVAL_P(type_url_php);
size_t type_url_len = Z_STRLEN_P(type_url_php);
if (url_prefix_len > type_url_len ||
strncmp(TYPE_URL_PREFIX, type_url, url_prefix_len) != 0) {
zend_throw_exception(
NULL, "Type url needs to be type.googleapis.com/fully-qulified",
0 TSRMLS_CC);
return;
}
const char* fully_qualified_name = type_url + url_prefix_len;
PHP_PROTO_HASHTABLE_VALUE desc_php = get_proto_obj(fully_qualified_name);
if (desc_php == NULL) {
zend_throw_exception(
NULL, "Specified message in any hasn't been added to descriptor pool",
0 TSRMLS_CC);
return;
}
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, desc_php);
zend_class_entry* klass = desc->klass;
ZVAL_OBJ(return_value, klass->create_object(klass TSRMLS_CC));
MessageHeader* msg = UNBOX(MessageHeader, return_value);
custom_data_init(klass, msg PHP_PROTO_TSRMLS_CC);
// Get value.
zval value_member;
PHP_PROTO_ZVAL_STRING(&value_member, "value", 1);
PHP_PROTO_FAKE_SCOPE_RESTART(any_type);
zval* value = php_proto_message_read_property(
getThis(), &value_member PHP_PROTO_TSRMLS_CC);
PHP_PROTO_FAKE_SCOPE_END;
merge_from_string(Z_STRVAL_P(value), Z_STRLEN_P(value), desc, msg);
}
PHP_METHOD(Any, pack) {
zval* val;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &val) ==
FAILURE) {
return;
}
if (!instanceof_function(Z_OBJCE_P(val), message_type TSRMLS_CC)) {
zend_error(E_USER_ERROR, "Given value is not an instance of Message.");
return;
}
// Set value by serialized data.
zval data;
serialize_to_string(val, &data TSRMLS_CC);
zval member;
PHP_PROTO_ZVAL_STRING(&member, "value", 1);
PHP_PROTO_FAKE_SCOPE_BEGIN(any_type);
message_handlers->write_property(getThis(), &member, &data,
NULL PHP_PROTO_TSRMLS_CC);
PHP_PROTO_FAKE_SCOPE_END;
// Set type url.
Descriptor* desc =
UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(val)));
const char* fully_qualified_name = upb_msgdef_fullname(desc->msgdef);
size_t type_url_len =
strlen(TYPE_URL_PREFIX) + strlen(fully_qualified_name) + 1;
char* type_url = ALLOC_N(char, type_url_len);
sprintf(type_url, "%s%s", TYPE_URL_PREFIX, fully_qualified_name);
zval type_url_php;
PHP_PROTO_ZVAL_STRING(&type_url_php, type_url, 1);
PHP_PROTO_ZVAL_STRING(&member, "type_url", 1);
PHP_PROTO_FAKE_SCOPE_RESTART(any_type);
message_handlers->write_property(getThis(), &member, &type_url_php,
NULL PHP_PROTO_TSRMLS_CC);
PHP_PROTO_FAKE_SCOPE_END;
FREE(type_url);
}
PHP_METHOD(Any, is) {
zend_class_entry *klass = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "C", &klass) ==
FAILURE) {
return;
}
PHP_PROTO_HASHTABLE_VALUE desc_php = get_ce_obj(klass);
if (desc_php == NULL) {
RETURN_BOOL(false);
}
// Create corresponded type url.
Descriptor* desc =
UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(klass));
const char* fully_qualified_name = upb_msgdef_fullname(desc->msgdef);
size_t type_url_len =
strlen(TYPE_URL_PREFIX) + strlen(fully_qualified_name) + 1;
char* type_url = ALLOC_N(char, type_url_len);
sprintf(type_url, "%s%s", TYPE_URL_PREFIX, fully_qualified_name);
// Fetch stored type url.
zval member;
PHP_PROTO_ZVAL_STRING(&member, "type_url", 1);
PHP_PROTO_FAKE_SCOPE_BEGIN(any_type);
zval* value =
php_proto_message_read_property(getThis(), &member PHP_PROTO_TSRMLS_CC);
PHP_PROTO_FAKE_SCOPE_END;
// Compare two type url.
bool is = strcmp(type_url, Z_STRVAL_P(value)) == 0;
FREE(type_url);
RETURN_BOOL(is);
}
......@@ -46,6 +46,9 @@ static HashTable* upb_def_to_php_obj_map;
// Global map from message/enum's php class entry to corresponding wrapper
// Descriptor/EnumDescriptor instances.
static HashTable* ce_to_php_obj_map;
// Global map from message/enum's proto fully-qualified name to corresponding
// wrapper Descriptor/EnumDescriptor instances.
static HashTable* proto_to_php_obj_map;
// -----------------------------------------------------------------------------
// Global maps.
......@@ -80,6 +83,22 @@ static void add_to_list(HashTable* t, void* value) {
(void**)&pDest);
}
static void add_to_strtable(HashTable* t, const char* key, int key_size,
void* value) {
zval* pDest = NULL;
php_proto_zend_hash_update_mem(t, key, key_size, &value, sizeof(void*),
(void**)&pDest);
}
static void* get_from_strtable(const HashTable* t, const char* key, int key_size) {
void** value;
if (php_proto_zend_hash_find_mem(t, key, key_size, (void**)&value) ==
FAILURE) {
return NULL;
}
return *value;
}
void add_def_obj(const void* def, PHP_PROTO_HASHTABLE_VALUE value) {
#if PHP_MAJOR_VERSION < 7
Z_ADDREF_P(value);
......@@ -110,6 +129,20 @@ bool class_added(const void* ce) {
return exist_in_table(ce_to_php_obj_map, ce);
}
void add_proto_obj(const char* proto, PHP_PROTO_HASHTABLE_VALUE value) {
#if PHP_MAJOR_VERSION < 7
Z_ADDREF_P(value);
#else
++GC_REFCOUNT(value);
#endif
add_to_strtable(proto_to_php_obj_map, proto, strlen(proto), value);
}
PHP_PROTO_HASHTABLE_VALUE get_proto_obj(const char* proto) {
return (PHP_PROTO_HASHTABLE_VALUE)get_from_strtable(proto_to_php_obj_map,
proto, strlen(proto));
}
// -----------------------------------------------------------------------------
// Utilities.
// -----------------------------------------------------------------------------
......@@ -163,6 +196,9 @@ static PHP_RINIT_FUNCTION(protobuf) {
ALLOC_HASHTABLE(ce_to_php_obj_map);
zend_hash_init(ce_to_php_obj_map, 16, NULL, HASHTABLE_VALUE_DTOR, 0);
ALLOC_HASHTABLE(proto_to_php_obj_map);
zend_hash_init(proto_to_php_obj_map, 16, NULL, HASHTABLE_VALUE_DTOR, 0);
generated_pool = NULL;
generated_pool_php = NULL;
internal_generated_pool_php = NULL;
......@@ -177,6 +213,9 @@ static PHP_RSHUTDOWN_FUNCTION(protobuf) {
zend_hash_destroy(ce_to_php_obj_map);
FREE_HASHTABLE(ce_to_php_obj_map);
zend_hash_destroy(proto_to_php_obj_map);
FREE_HASHTABLE(proto_to_php_obj_map);
#if PHP_MAJOR_VERSION < 7
if (generated_pool_php != NULL) {
zval_dtor(generated_pool_php);
......@@ -217,6 +256,7 @@ static PHP_MINIT_FUNCTION(protobuf) {
repeated_field_init(TSRMLS_C);
repeated_field_iter_init(TSRMLS_C);
util_init(TSRMLS_C);
any_init(TSRMLS_C);
return 0;
}
......
This diff is collapsed.
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: google/protobuf/any.proto
namespace GPBMetadata\Google\Protobuf;
class Any
{
public static $is_initialized = false;
public static function initOnce() {
$pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
if (static::$is_initialized == true) {
return;
}
$pool->internalAddGeneratedFile(hex2bin(
"0acd010a19676f6f676c652f70726f746f6275662f616e792e70726f746f" .
"120f676f6f676c652e70726f746f62756622260a03416e7912100a087479" .
"70655f75726c180120012809120d0a0576616c756518022001280c426f0a" .
"13636f6d2e676f6f676c652e70726f746f6275664208416e7950726f746f" .
"50015a256769746875622e636f6d2f676f6c616e672f70726f746f627566" .
"2f7074797065732f616e79a20203475042aa021e476f6f676c652e50726f" .
"746f6275662e57656c6c4b6e6f776e5479706573620670726f746f33"
));
static::$is_initialized = true;
}
}
This diff is collapsed.
......@@ -3,7 +3,7 @@
# gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so `which
# phpunit` --bootstrap autoload.php tmp_test.php
#
gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so `which phpunit` --bootstrap autoload.php encode_decode_test.php
gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so `which phpunit` --bootstrap autoload.php well_known_test.php
#
# gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
#
......
<?php
require_once('test_base.php');
require_once('test_util.php');
use Google\Protobuf\GPBEmpty;
use Google\Protobuf\Any;
use Foo\TestMessage;
class NotMessage {}
class WellKnownTest extends PHPUnit_Framework_TestCase {
class WellKnownTest extends TestBase {
public function testNone()
{
......@@ -14,4 +22,68 @@ class WellKnownTest extends PHPUnit_Framework_TestCase {
$msg = new TestImportDescriptorProto();
}
public function testAny()
{
// Create embed message
$embed = new TestMessage();
$this->setFields($embed);
$data = $embed->serializeToString();
// Set any via normal setter.
$any = new Any();
$this->assertSame(
$any, $any->setTypeUrl("type.googleapis.com/foo.TestMessage"));
$this->assertSame("type.googleapis.com/foo.TestMessage",
$any->getTypeUrl());
$this->assertSame($any, $any->setValue($data));
$this->assertSame($data, $any->getValue());
// Test unpack.
$msg = $any->unpack();
$this->assertTrue($msg instanceof TestMessage);
$this->expectFields($msg);
// Test pack.
$any = new Any();
$any->pack($embed);
$this->assertSame($data, $any->getValue());
$this->assertSame("type.googleapis.com/foo.TestMessage", $any->getTypeUrl());
// Test is.
$this->assertTrue($any->is(TestMessage::class));
$this->assertFalse($any->is(Any::class));
}
/**
* @expectedException Exception
*/
public function testAnyUnpackInvalidTypeUrl()
{
$any = new Any();
$any->setTypeUrl("invalid");
$any->unpack();
}
/**
* @expectedException Exception
*/
public function testAnyUnpackMessageNotAdded()
{
$any = new Any();
$any->setTypeUrl("type.googleapis.com/MessageNotAdded");
$any->unpack();
}
/**
* @expectedException Exception
*/
public function testAnyUnpackDecodeError()
{
$any = new Any();
$any->setTypeUrl("type.googleapis.com/foo.TestMessage");
$any->setValue("abc");
$any->unpack();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment