From d4ca92962c40637abbce61d14a8675f43bafb6a9 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Tue, 11 Aug 2020 19:30:46 -0700 Subject: [PATCH] Port php c extension to php8 (#7793) * Only ported c extension to php8. * Didn't fixed the issue of throwing warnings for missing arginfo in bundled files. * Tests not fixed, because syntax of phpunit (<7 vs >9.3) are not compatible. * In next release, needs to drop php5 and php7.0 support (in order to use phpunit > 7) --- .gitignore | 2 + Makefile.am | 20 ++-- kokoro/linux/php80/build.sh | 18 ++++ kokoro/linux/php80/continuous.cfg | 11 +++ kokoro/linux/php80/presubmit.cfg | 11 +++ php/ext/google/protobuf/array.c | 18 +++- php/ext/google/protobuf/convert.c | 61 +++++++++--- php/ext/google/protobuf/map.c | 16 +++- php/ext/google/protobuf/message.c | 93 ++++++++++++------- php/ext/google/protobuf/protobuf.c | 7 ++ php/ext/google/protobuf/protobuf.h | 28 ++++++ php/phpunit.xml | 20 ++-- php/tests/{array_test.php => ArrayTest.php} | 2 +- ...scriptors_test.php => DescriptorsTest.php} | 0 ...e_decode_test.php => EncodeDecodeTest.php} | 0 ..._class_test.php => GeneratedClassTest.php} | 0 ...hpdoc_test.php => GeneratedPhpdocTest.php} | 0 ...vice_test.php => GeneratedServiceTest.php} | 0 .../{map_field_test.php => MapFieldTest.php} | 0 ...ion_test.php => PhpImplementationTest.php} | 0 ...{well_known_test.php => WellKnownTest.php} | 0 ...rs_test.php => WrapperTypeSettersTest.php} | 0 php/tests/test.sh | 5 +- tests.sh | 45 +++++++++ 24 files changed, 282 insertions(+), 75 deletions(-) create mode 100755 kokoro/linux/php80/build.sh create mode 100644 kokoro/linux/php80/continuous.cfg create mode 100644 kokoro/linux/php80/presubmit.cfg rename php/tests/{array_test.php => ArrayTest.php} (99%) rename php/tests/{descriptors_test.php => DescriptorsTest.php} (100%) rename php/tests/{encode_decode_test.php => EncodeDecodeTest.php} (100%) rename php/tests/{generated_class_test.php => GeneratedClassTest.php} (100%) rename php/tests/{generated_phpdoc_test.php => GeneratedPhpdocTest.php} (100%) rename php/tests/{generated_service_test.php => GeneratedServiceTest.php} (100%) rename php/tests/{map_field_test.php => MapFieldTest.php} (100%) rename php/tests/{php_implementation_test.php => PhpImplementationTest.php} (100%) rename php/tests/{well_known_test.php => WellKnownTest.php} (100%) rename php/tests/{wrapper_type_setters_test.php => WrapperTypeSettersTest.php} (100%) diff --git a/.gitignore b/.gitignore index 7235f6b78..9c1484add 100644 --- a/.gitignore +++ b/.gitignore @@ -137,8 +137,10 @@ conformance/*.class # php test output composer.lock +php/tests/.phpunit.result.cache php/tests/generated/ php/tests/old_protoc +php/tests/phpunit-9.phar php/tests/protobuf/ php/tests/core php/tests/vgcore* diff --git a/Makefile.am b/Makefile.am index 15b5a4203..bced2167a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -915,23 +915,23 @@ php_EXTRA_DIST= \ php/src/Google/Protobuf/UInt64Value.php \ php/src/Google/Protobuf/Value.php \ php/src/phpdoc.dist.xml \ - php/tests/array_test.php \ + php/tests/ArrayTest.php \ php/tests/autoload.php \ php/tests/bootstrap_phpunit.php \ php/tests/compatibility_test.sh \ php/tests/compile_extension.sh \ - php/tests/descriptors_test.php \ - php/tests/encode_decode_test.php \ + php/tests/DescriptorsTest.php \ + php/tests/EncodeDecodeTest.php \ php/tests/gdb_test.sh \ php/tests/generate_protos.sh \ - php/tests/generated_class_test.php \ - php/tests/generated_phpdoc_test.php \ - php/tests/generated_service_test.php \ - php/tests/map_field_test.php \ + php/tests/GeneratedClassTest.php \ + php/tests/GeneratedPhpdocTest.php \ + php/tests/GeneratedServiceTest.php \ + php/tests/MapFieldTest.php \ php/tests/memory_leak_test.php \ php/tests/multirequest.php \ php/tests/multirequest.sh \ - php/tests/php_implementation_test.php \ + php/tests/PhpImplementationTest.php \ php/tests/proto/empty/echo.proto \ php/tests/proto/test.proto \ php/tests/proto/test_descriptors.proto \ @@ -955,8 +955,8 @@ php_EXTRA_DIST= \ php/tests/test_util.php \ php/tests/undefined_test.php \ php/tests/valgrind.supp \ - php/tests/well_known_test.php \ - php/tests/wrapper_type_setters_test.php + php/tests/WellKnownTest.php \ + php/tests/WrapperTypeSettersTest.php python_EXTRA_DIST= \ python/MANIFEST.in \ diff --git a/kokoro/linux/php80/build.sh b/kokoro/linux/php80/build.sh new file mode 100755 index 000000000..6499b39af --- /dev/null +++ b/kokoro/linux/php80/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# This is the top-level script we give to Kokoro as the entry point for +# running the "pull request" project: +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +# Change to repo root +cd $(dirname $0)/../../.. + +export DOCKERHUB_ORGANIZATION=protobuftesting +export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/php +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="php8.0_all" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/php80/continuous.cfg b/kokoro/linux/php80/continuous.cfg new file mode 100644 index 000000000..8426318bb --- /dev/null +++ b/kokoro/linux/php80/continuous.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/php80/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/php80/presubmit.cfg b/kokoro/linux/php80/presubmit.cfg new file mode 100644 index 000000000..8426318bb --- /dev/null +++ b/kokoro/linux/php80/presubmit.cfg @@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/php80/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/php/ext/google/protobuf/array.c b/php/ext/google/protobuf/array.c index 443bdb109..4615ed31a 100644 --- a/php/ext/google/protobuf/array.c +++ b/php/ext/google/protobuf/array.c @@ -94,11 +94,12 @@ static void RepeatedField_destructor(zend_object* obj) { zend_object_std_dtor(&intern->std); } -static HashTable *RepeatedField_GetProperties(zval *object) { +static HashTable *RepeatedField_GetProperties(PROTO_VAL *object) { return NULL; // We do not have a properties table. } -static zval *RepeatedField_GetPropertyPtrPtr(zval *object, zval *member, +static zval *RepeatedField_GetPropertyPtrPtr(PROTO_VAL *object, + PROTO_STR *member, int type, void **cache_slot) { return NULL; // We don't offer direct references to our properties. } @@ -392,6 +393,15 @@ PHP_METHOD(RepeatedField, getIterator) { RETURN_ZVAL(&ret, 0, 1); } +ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 1) + ZEND_ARG_INFO(0, type) + ZEND_ARG_INFO(0, class) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_append, 0, 0, 1) + ZEND_ARG_INFO(0, newval) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() @@ -405,8 +415,8 @@ ZEND_BEGIN_ARG_INFO(arginfo_void, 0) ZEND_END_ARG_INFO() static zend_function_entry repeated_field_methods[] = { - PHP_ME(RepeatedField, __construct, NULL, ZEND_ACC_PUBLIC) - PHP_ME(RepeatedField, append, NULL, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedField, __construct, arginfo_construct, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedField, append, arginfo_append, ZEND_ACC_PUBLIC) PHP_ME(RepeatedField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC) PHP_ME(RepeatedField, offsetGet, arginfo_offsetGet, ZEND_ACC_PUBLIC) PHP_ME(RepeatedField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC) diff --git a/php/ext/google/protobuf/convert.c b/php/ext/google/protobuf/convert.c index dd076c5f1..1c2f6288b 100644 --- a/php/ext/google/protobuf/convert.c +++ b/php/ext/google/protobuf/convert.c @@ -92,20 +92,55 @@ PHP_METHOD(Util, checkRepeatedField) { RETURN_ZVAL(val, 1, 0); } +ZEND_BEGIN_ARG_INFO_EX(arginfo_checkPrimitive, 0, 0, 1) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_checkMessage, 0, 0, 2) + ZEND_ARG_INFO(0, value) + ZEND_ARG_INFO(0, class) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_checkMapField, 0, 0, 3) + ZEND_ARG_INFO(0, value) + ZEND_ARG_INFO(0, key_type) + ZEND_ARG_INFO(0, value_type) + ZEND_ARG_INFO(0, value_class) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_checkRepeatedField, 0, 0, 2) + ZEND_ARG_INFO(0, value) + ZEND_ARG_INFO(0, type) + ZEND_ARG_INFO(0, class) +ZEND_END_ARG_INFO() + static zend_function_entry util_methods[] = { - PHP_ME(Util, checkInt32, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkUint32, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkInt64, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkUint64, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkEnum, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkFloat, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkDouble, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkBool, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkString, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkBytes, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkMessage, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkMapField, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkRepeatedField, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkInt32, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkUint32, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkInt64, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkUint64, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkEnum, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkFloat, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkDouble, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkBool, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkString, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkBytes, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkMessage, arginfo_checkMessage, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkMapField, arginfo_checkMapField, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkRepeatedField, arginfo_checkRepeatedField, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_FE_END }; diff --git a/php/ext/google/protobuf/map.c b/php/ext/google/protobuf/map.c index 7919d51a9..f29c18c9b 100644 --- a/php/ext/google/protobuf/map.c +++ b/php/ext/google/protobuf/map.c @@ -90,12 +90,12 @@ static void MapField_destructor(zend_object* obj) { zend_object_std_dtor(&intern->std); } -static zval *Map_GetPropertyPtrPtr(zval *object, zval *member, int type, - void **cache_slot) { +static zval *Map_GetPropertyPtrPtr(PROTO_VAL *object, PROTO_STR *member, + int type, void **cache_slot) { return NULL; // We don't offer direct references to our properties. } -static HashTable *map_get_properties(zval *object) { +static HashTable *Map_GetProperties(PROTO_VAL *object) { return NULL; // We do not have a properties table. } @@ -378,6 +378,12 @@ PHP_METHOD(MapField, getIterator) { RETURN_ZVAL(&ret, 0, 1); } +ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 2) + ZEND_ARG_INFO(0, key_type) + ZEND_ARG_INFO(0, value_type) + ZEND_ARG_INFO(0, value_class) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() @@ -391,7 +397,7 @@ ZEND_BEGIN_ARG_INFO(arginfo_void, 0) ZEND_END_ARG_INFO() static zend_function_entry MapField_methods[] = { - PHP_ME(MapField, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(MapField, __construct, arginfo_construct, ZEND_ACC_PUBLIC) PHP_ME(MapField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC) PHP_ME(MapField, offsetGet, arginfo_offsetGet, ZEND_ACC_PUBLIC) PHP_ME(MapField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC) @@ -572,7 +578,7 @@ void Map_ModuleInit() { h = &MapField_object_handlers; memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); h->dtor_obj = MapField_destructor; - h->get_properties = map_get_properties; + h->get_properties = Map_GetProperties; h->get_property_ptr_ptr = Map_GetPropertyPtrPtr; INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\MapFieldIter", diff --git a/php/ext/google/protobuf/message.c b/php/ext/google/protobuf/message.c index 3a0eb9369..63d2b084a 100644 --- a/php/ext/google/protobuf/message.c +++ b/php/ext/google/protobuf/message.c @@ -95,10 +95,10 @@ static void Message_dtor(zend_object* obj) { * * Helper function to look up a field given a member name (as a string). */ -static const upb_fielddef *get_field(Message *msg, zval *member) { +static const upb_fielddef *get_field(Message *msg, PROTO_STR *member) { const upb_msgdef *m = msg->desc->msgdef; const upb_fielddef *f = - upb_msgdef_ntof(m, Z_STRVAL_P(member), Z_STRLEN_P(member)); + upb_msgdef_ntof(m, PROTO_STRVAL_P(member), PROTO_STRLEN_P(member)); if (!f) { zend_throw_exception_ex(NULL, 0, "No such property %s.", @@ -126,9 +126,10 @@ static const upb_fielddef *get_field(Message *msg, zval *member) { * return isset($this->optional_int32); * } */ -static int Message_has_property(zval *obj, zval *member, int has_set_exists, +static int Message_has_property(PROTO_VAL *obj, PROTO_STR *member, + int has_set_exists, void **cache_slot) { - Message* intern = (Message*)Z_OBJ_P(obj); + Message* intern = PROTO_MSG_P(obj); const upb_fielddef *f = get_field(intern, member); if (!f) return 0; @@ -161,8 +162,9 @@ static int Message_has_property(zval *obj, zval *member, int has_set_exists, * unset($this->optional_int32); * } */ -static void Message_unset_property(zval *obj, zval *member, void **cache_slot) { - Message* intern = (Message*)Z_OBJ_P(obj); +static void Message_unset_property(PROTO_VAL *obj, PROTO_STR *member, + void **cache_slot) { + Message* intern = PROTO_MSG_P(obj); const upb_fielddef *f = get_field(intern, member); if (!f) return; @@ -196,9 +198,9 @@ static void Message_unset_property(zval *obj, zval *member, void **cache_slot) { * We lookup the field and return the scalar, RepeatedField, or MapField for * this field. */ -static zval *Message_read_property(zval *obj, zval *member, int type, - void **cache_slot, zval *rv) { - Message* intern = (Message*)Z_OBJ_P(obj); +static zval *Message_read_property(PROTO_VAL *obj, PROTO_STR *member, + int type, void **cache_slot, zval *rv) { + Message* intern = PROTO_MSG_P(obj); const upb_fielddef *f = get_field(intern, member); upb_arena *arena = Arena_Get(&intern->arena); @@ -240,29 +242,41 @@ static zval *Message_read_property(zval *obj, zval *member, int type, * The C extension version of checkInt32() doesn't actually check anything, so * we perform all checking and conversion in this function. */ -static void Message_write_property(zval *obj, zval *member, zval *val, - void **cache_slot) { - Message* intern = (Message*)Z_OBJ_P(obj); +static PROTO_RETURN_VAL Message_write_property( + PROTO_VAL *obj, PROTO_STR *member, zval *val, void **cache_slot) { + Message* intern = PROTO_MSG_P(obj); const upb_fielddef *f = get_field(intern, member); upb_arena *arena = Arena_Get(&intern->arena); upb_msgval msgval; - if (!f) return; + if (!f) goto error; if (upb_fielddef_ismap(f)) { msgval.map_val = MapField_GetUpbMap(val, f, arena); - if (!msgval.map_val) return; + if (!msgval.map_val) goto error; } else if (upb_fielddef_isseq(f)) { msgval.array_val = RepeatedField_GetUpbArray(val, f, arena); - if (!msgval.array_val) return; + if (!msgval.array_val) goto error; } else { upb_fieldtype_t type = upb_fielddef_type(f); const Descriptor *subdesc = Descriptor_GetFromFieldDef(f); bool ok = Convert_PhpToUpb(val, &msgval, type, subdesc, arena); - if (!ok) return; + if (!ok) goto error; } upb_msg_set(intern->msg, f, msgval, arena); +#if PHP_VERSION_ID < 704000 + return; +#else + return val; +#endif + +error: +#if PHP_VERSION_ID < 704000 + return; +#else + return &EG(error_zval); +#endif } /** @@ -272,7 +286,8 @@ static void Message_write_property(zval *obj, zval *member, zval *val, * reference to our internal properties. We don't support this, so we return * NULL. */ -static zval *Message_get_property_ptr_ptr(zval *object, zval *member, int type, +static zval *Message_get_property_ptr_ptr(PROTO_VAL *object, PROTO_STR *member, + int type, void **cache_slot) { return NULL; // We do not have a properties table. } @@ -283,7 +298,7 @@ static zval *Message_get_property_ptr_ptr(zval *object, zval *member, int type, * Object handler for the get_properties event in PHP. This returns a HashTable * of our internal properties. We don't support this, so we return NULL. */ -static HashTable *Message_get_properties(zval *object) { +static HashTable *Message_get_properties(PROTO_VAL *object) { return NULL; // We don't offer direct references to our properties. } @@ -870,20 +885,36 @@ PHP_METHOD(Message, writeOneof) { upb_msg_set(intern->msg, f, msgval, arena); } +ZEND_BEGIN_ARG_INFO_EX(arginfo_void, 0, 0, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_mergeFrom, 0, 0, 1) + ZEND_ARG_INFO(0, data) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_read, 0, 0, 1) + ZEND_ARG_INFO(0, field) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_write, 0, 0, 2) + ZEND_ARG_INFO(0, field) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + static zend_function_entry Message_methods[] = { - PHP_ME(Message, clear, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Message, discardUnknownFields, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Message, serializeToString, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Message, mergeFromString, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Message, serializeToJsonString, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Message, mergeFromJsonString, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Message, mergeFrom, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Message, readWrapperValue, NULL, ZEND_ACC_PROTECTED) - PHP_ME(Message, writeWrapperValue, NULL, ZEND_ACC_PROTECTED) - PHP_ME(Message, readOneof, NULL, ZEND_ACC_PROTECTED) - PHP_ME(Message, writeOneof, NULL, ZEND_ACC_PROTECTED) - PHP_ME(Message, whichOneof, NULL, ZEND_ACC_PROTECTED) - PHP_ME(Message, __construct, NULL, ZEND_ACC_PROTECTED) + PHP_ME(Message, clear, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(Message, discardUnknownFields, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(Message, serializeToString, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(Message, mergeFromString, arginfo_mergeFrom, ZEND_ACC_PUBLIC) + PHP_ME(Message, serializeToJsonString, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(Message, mergeFromJsonString, arginfo_mergeFrom, ZEND_ACC_PUBLIC) + PHP_ME(Message, mergeFrom, arginfo_mergeFrom, ZEND_ACC_PUBLIC) + PHP_ME(Message, readWrapperValue, arginfo_read, ZEND_ACC_PROTECTED) + PHP_ME(Message, writeWrapperValue, arginfo_write, ZEND_ACC_PROTECTED) + PHP_ME(Message, readOneof, arginfo_read, ZEND_ACC_PROTECTED) + PHP_ME(Message, writeOneof, arginfo_write, ZEND_ACC_PROTECTED) + PHP_ME(Message, whichOneof, arginfo_read, ZEND_ACC_PROTECTED) + PHP_ME(Message, __construct, arginfo_void, ZEND_ACC_PROTECTED) ZEND_FE_END }; diff --git a/php/ext/google/protobuf/protobuf.c b/php/ext/google/protobuf/protobuf.c index 15c8f9bd7..fa1cc114b 100644 --- a/php/ext/google/protobuf/protobuf.c +++ b/php/ext/google/protobuf/protobuf.c @@ -273,11 +273,18 @@ const upb_msgdef *NameMap_GetMessage(zend_class_entry *ce) { zend_hash_find_ptr(&PROTOBUF_G(name_msg_cache), ce->name); if (!ret && ce->create_object) { +#if PHP_VERSION_ID < 80000 zval tmp; zval zv; ZVAL_OBJ(&tmp, ce->create_object(ce)); zend_call_method_with_0_params(&tmp, ce, NULL, "__construct", &zv); zval_ptr_dtor(&tmp); +#else + zval zv; + zend_object *tmp = ce->create_object(ce); + zend_call_method_with_0_params(tmp, ce, NULL, "__construct", &zv); + OBJ_RELEASE(tmp); +#endif zval_ptr_dtor(&zv); ret = zend_hash_find_ptr(&PROTOBUF_G(name_msg_cache), ce->name); } diff --git a/php/ext/google/protobuf/protobuf.h b/php/ext/google/protobuf/protobuf.h index 6a7afae06..15cb34407 100644 --- a/php/ext/google/protobuf/protobuf.h +++ b/php/ext/google/protobuf/protobuf.h @@ -43,6 +43,34 @@ const zval *get_generated_pool(); #define GC_DELREF(h) --GC_REFCOUNT(h) #endif +// Since php 7.4, the write_property() object handler now returns the assigned +// value (after possible type coercions) rather than void. +// https://github.com/php/php-src/blob/PHP-7.4.0/UPGRADING.INTERNALS#L171-L173 +#if PHP_VERSION_ID < 70400 +#define PROTO_RETURN_VAL void +#else +#define PROTO_RETURN_VAL zval* +#endif + +// Sine php 8.0, the Object Handlers API was changed to receive zend_object* +// instead of zval* and zend_string* instead of zval* for property names. +// https://github.com/php/php-src/blob/php-8.0.0beta1/UPGRADING.INTERNALS#L37-L39 +#if PHP_VERSION_ID < 80000 +#define PROTO_VAL zval +#define PROTO_STR zval +#define PROTO_MSG_P(obj) (Message*)Z_OBJ_P(obj) +#define PROTO_STRVAL_P(obj) Z_STRVAL_P(obj) +#define PROTO_STRLEN_P(obj) Z_STRLEN_P(obj) +#else +#define PROTO_VAL zend_object +#define PROTO_STR zend_string +#define PROTO_MSG_P(obj) (Message*)(obj) +#define PROTO_STRVAL_P(obj) ZSTR_VAL(obj) +#define PROTO_STRLEN_P(obj) ZSTR_LEN(obj) +#endif + +#define PHP_PROTOBUF_VERSION "4.0.0RC2" + // ptr -> PHP object cache. This is a weak map that caches lazily-created // wrapper objects around upb types: // * upb_msg* -> Message diff --git a/php/phpunit.xml b/php/phpunit.xml index 769037cf9..8e7583596 100644 --- a/php/phpunit.xml +++ b/php/phpunit.xml @@ -3,16 +3,16 @@ colors="true"> - tests/php_implementation_test.php - tests/array_test.php - tests/encode_decode_test.php - tests/generated_class_test.php - tests/generated_phpdoc_test.php - tests/map_field_test.php - tests/well_known_test.php - tests/descriptors_test.php - tests/generated_service_test.php - tests/wrapper_type_setters_test.php + tests/PhpImplementationTest.php + tests/ArrayTest.php + tests/EncodeDecodeTest.php + tests/GeneratedClassTest.php + tests/GeneratedPhpdocTest.php + tests/MapFieldTest.php + tests/WellKnownTest.php + tests/DescriptorsTest.php + tests/GeneratedServiceTest.php + tests/WrapperTypeSettersTest.php diff --git a/php/tests/array_test.php b/php/tests/ArrayTest.php similarity index 99% rename from php/tests/array_test.php rename to php/tests/ArrayTest.php index b25140408..2cb4b3910 100644 --- a/php/tests/array_test.php +++ b/php/tests/ArrayTest.php @@ -7,7 +7,7 @@ use Google\Protobuf\Internal\GPBType; use Foo\TestMessage; use Foo\TestMessage\Sub; -class RepeatedFieldTest extends \PHPUnit\Framework\TestCase +class ArrayTest extends \PHPUnit\Framework\TestCase { ######################################################### diff --git a/php/tests/descriptors_test.php b/php/tests/DescriptorsTest.php similarity index 100% rename from php/tests/descriptors_test.php rename to php/tests/DescriptorsTest.php diff --git a/php/tests/encode_decode_test.php b/php/tests/EncodeDecodeTest.php similarity index 100% rename from php/tests/encode_decode_test.php rename to php/tests/EncodeDecodeTest.php diff --git a/php/tests/generated_class_test.php b/php/tests/GeneratedClassTest.php similarity index 100% rename from php/tests/generated_class_test.php rename to php/tests/GeneratedClassTest.php diff --git a/php/tests/generated_phpdoc_test.php b/php/tests/GeneratedPhpdocTest.php similarity index 100% rename from php/tests/generated_phpdoc_test.php rename to php/tests/GeneratedPhpdocTest.php diff --git a/php/tests/generated_service_test.php b/php/tests/GeneratedServiceTest.php similarity index 100% rename from php/tests/generated_service_test.php rename to php/tests/GeneratedServiceTest.php diff --git a/php/tests/map_field_test.php b/php/tests/MapFieldTest.php similarity index 100% rename from php/tests/map_field_test.php rename to php/tests/MapFieldTest.php diff --git a/php/tests/php_implementation_test.php b/php/tests/PhpImplementationTest.php similarity index 100% rename from php/tests/php_implementation_test.php rename to php/tests/PhpImplementationTest.php diff --git a/php/tests/well_known_test.php b/php/tests/WellKnownTest.php similarity index 100% rename from php/tests/well_known_test.php rename to php/tests/WellKnownTest.php diff --git a/php/tests/wrapper_type_setters_test.php b/php/tests/WrapperTypeSettersTest.php similarity index 100% rename from php/tests/wrapper_type_setters_test.php rename to php/tests/WrapperTypeSettersTest.php diff --git a/php/tests/test.sh b/php/tests/test.sh index 4beeed523..29511326a 100755 --- a/php/tests/test.sh +++ b/php/tests/test.sh @@ -18,6 +18,9 @@ case "$PHP_VERSION" in 7.3.*|7.4.*) PHPUNIT=phpunit-8.phar ;; + 8.0.*) + PHPUNIT=phpunit-9.phar + ;; *) echo "ERROR: Unsupported PHP version $PHP_VERSION" exit 1 @@ -26,7 +29,7 @@ esac [ -f $PHPUNIT ] || wget https://phar.phpunit.de/$PHPUNIT -tests=( array_test.php encode_decode_test.php generated_class_test.php map_field_test.php well_known_test.php descriptors_test.php wrapper_type_setters_test.php) +tests=( ArrayTest.php EncodeDecodeTest.php GeneratedClassTest.php MapFieldTest.php WellKnownTest.php DescriptorsTest.php WrapperTypeSettersTest.php) for t in "${tests[@]}" do diff --git a/tests.sh b/tests.sh index ca787ca69..3d47b6cbf 100755 --- a/tests.sh +++ b/tests.sh @@ -701,6 +701,51 @@ build_php7.4_zts_c() { popd } +build_php8.0() { + use_php 8.0 + pushd php + rm -rf vendor + composer update + composer test + popd + (cd conformance && make test_php) +} + +build_php8.0_c() { + IS_64BIT=$1 + use_php 8.0 + php/tests/test.sh + pushd conformance + if [ "$IS_64BIT" = "true" ] + then + make test_php_c + else + make test_php_c_32 + fi + popd +} + +build_php8.0_c_64() { + build_php8.0_c true +} + +build_php8.0_mixed() { + use_php 8.0 + pushd php + rm -rf vendor + composer update + tests/compile_extension.sh + tests/generate_protos.sh + php -dextension=./ext/google/protobuf/modules/protobuf.so ./vendor/bin/phpunit + popd +} + +build_php8.0_all() { + build_php8.0 + build_php8.0_c_64 + build_php8.0_mixed +} + build_php_all_32() { build_php5.5 build_php5.6