Skip to content

Commit deead96

Browse files
authored
PHPC-1716 Allow configuring server API version in manager (#1204)
* Introduce MongoDB\Driver\ServerApi * Accept serverApi driver option * Introduce create_test_manager factory to create manager A centralised entry point is required to inject the API_VERSION env variable later. * Add build variant to test with requireApiVersion=true * Fix wrong configuration for auth variable This changed when migrating from our own scripts to drivers-evergreen-tools and was not updated properly, causing all tests to run with auth disabled. * Declare ZEND_PARSE_PARAMETERS_NONE macro This macro is missing on PHP < 7.3 * Remove duplicated API param storage * Add missing semicolons * Add ZEND_PARSE_PARAMETERS_NON_EX macro * Extract error handling functionality to separate macros * Throw if internal mongoc_server_api_t is already initialised * Use imported namespaces in tools file * Fix type info for reflection * Use American English spelling * Only use typed serialize signature on PHP 8+ * Update PHONGO_PARSE_PARAMETERS_NONE macro for PHP < 7.3 * Remove usage of ZEND_STRL within zend_hash_str_add This causes compile failures on PHP < 7.3 that I have yet to understand. * Fix errors in new PHONGO_PARSE_PARAMETERS macros
1 parent 9f854a4 commit deead96

File tree

1,653 files changed

+2699
-1748
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,653 files changed

+2699
-1748
lines changed

.evergreen/config.yml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ functions:
386386
working_dir: "src"
387387
script: |
388388
${PREPARE_SHELL}
389-
TESTS=${TESTS} SSL=${SSL} MONGODB_URI="${MONGODB_URI}${APPEND_URI}" sh ${PROJECT_DIRECTORY}/.evergreen/run-tests.sh
389+
API_VERSION=${API_VERSION} TESTS=${TESTS} SSL=${SSL} MONGODB_URI="${MONGODB_URI}${APPEND_URI}" sh ${PROJECT_DIRECTORY}/.evergreen/run-tests.sh
390390
391391
"cleanup":
392392
- command: shell.exec
@@ -585,6 +585,19 @@ tasks:
585585
vars:
586586
TESTS: "tests/atlas.phpt"
587587

588+
- name: "test-requireApiVersion"
589+
tags: ["versioned_api"]
590+
commands:
591+
- func: "compile driver"
592+
- func: "bootstrap mongo-orchestration"
593+
vars:
594+
TOPOLOGY: "server"
595+
AUTH: "auth"
596+
REQUIRE_API_VERSION: "yes"
597+
- func: "run tests"
598+
vars:
599+
API_VERSION: "1"
600+
588601
- name: "ocsp-test_1-rsa-delegate"
589602
tags: ["ocsp"]
590603
commands:
@@ -1180,3 +1193,9 @@ buildvariants:
11801193
display_name: "OCSP tests - ${versions}"
11811194
tasks:
11821195
- name: ".ocsp"
1196+
1197+
- matrix_name: "test-requireApiVersion"
1198+
matrix_spec: { "os-php7": "debian92-test", "php-versions": "7.3", "versions": "latest" }
1199+
display_name: "Versioned API - ${versions}"
1200+
tasks:
1201+
- name: "test-requireApiVersion"

.evergreen/run-tests.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ AUTH=${AUTH:-noauth}
1111
SSL=${SSL:-nossl}
1212
MONGODB_URI=${MONGODB_URI:-}
1313
TESTS=${TESTS:-}
14+
API_VERSION=${API_VERSION:-}
1415

1516
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
1617
[ -z "$MARCH" ] && MARCH=$(uname -m | tr '[:upper:]' '[:lower:]')
@@ -26,7 +27,7 @@ echo "Running $AUTH tests, connecting to $MONGODB_URI"
2627
# Run the tests, and store the results in a junit result file
2728
case "$OS" in
2829
*)
29-
TEST_PHP_JUNIT="${PROJECT_DIRECTORY}/test-results.xml" TEST_PHP_ARGS="-q -x --show-diff -g FAIL,XFAIL,BORK,WARN,LEAK,SKIP" make test TESTS=$TESTS
30+
API_VERSION="${API_VERSION}" TEST_PHP_JUNIT="${PROJECT_DIRECTORY}/test-results.xml" TEST_PHP_ARGS="-q -x --show-diff -g FAIL,XFAIL,BORK,WARN,LEAK,SKIP" make test TESTS=$TESTS
3031
;;
3132
esac
3233

config.m4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ if test "$PHP_MONGODB" != "no"; then
143143
src/MongoDB/ReadConcern.c \
144144
src/MongoDB/ReadPreference.c \
145145
src/MongoDB/Server.c \
146+
src/MongoDB/ServerApi.c \
146147
src/MongoDB/Session.c \
147148
src/MongoDB/WriteConcern.c \
148149
src/MongoDB/WriteConcernError.c \

config.w32

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ if (PHP_MONGODB != "no") {
120120
EXTENSION("mongodb", "php_phongo.c phongo_compat.c", null, PHP_MONGODB_CFLAGS);
121121
MONGODB_ADD_SOURCES("/src", "bson.c bson-encode.c");
122122
MONGODB_ADD_SOURCES("/src/BSON", "Binary.c BinaryInterface.c DBPointer.c Decimal128.c Decimal128Interface.c Int64.c Javascript.c JavascriptInterface.c MaxKey.c MaxKeyInterface.c MinKey.c MinKeyInterface.c ObjectId.c ObjectIdInterface.c Persistable.c Regex.c RegexInterface.c Serializable.c Symbol.c Timestamp.c TimestampInterface.c Type.c Undefined.c Unserializable.c UTCDateTime.c UTCDateTimeInterface.c functions.c");
123-
MONGODB_ADD_SOURCES("/src/MongoDB", "BulkWrite.c ClientEncryption.c Command.c Cursor.c CursorId.c CursorInterface.c Manager.c Query.c ReadConcern.c ReadPreference.c Server.c Session.c WriteConcern.c WriteConcernError.c WriteError.c WriteResult.c");
123+
MONGODB_ADD_SOURCES("/src/MongoDB", "BulkWrite.c ClientEncryption.c Command.c Cursor.c CursorId.c CursorInterface.c Manager.c Query.c ReadConcern.c ReadPreference.c Server.c ServerApi.c Session.c WriteConcern.c WriteConcernError.c WriteError.c WriteResult.c");
124124
MONGODB_ADD_SOURCES("/src/MongoDB/Exception", "AuthenticationException.c BulkWriteException.c CommandException.c ConnectionException.c ConnectionTimeoutException.c EncryptionException.c Exception.c ExecutionTimeoutException.c InvalidArgumentException.c LogicException.c RuntimeException.c ServerException.c SSLConnectionException.c UnexpectedValueException.c WriteException.c");
125125
MONGODB_ADD_SOURCES("/src/MongoDB/Monitoring", "CommandFailedEvent.c CommandStartedEvent.c CommandSubscriber.c CommandSucceededEvent.c Subscriber.c functions.c");
126126
MONGODB_ADD_SOURCES("/src/libmongoc/src/common", PHP_MONGODB_COMMON_SOURCES);

phongo_compat.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,55 @@
169169
} while (0)
170170
#endif /* PHP_VERSION_ID < 70300 */
171171

172+
/* Compatibility macros to override error handling logic */
173+
#define PHONGO_PARSE_PARAMETERS_START(min_num_args, max_num_args) \
174+
do { \
175+
zend_error_handling error_handling; \
176+
zend_replace_error_handling( \
177+
EH_THROW, \
178+
phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), \
179+
&error_handling); \
180+
ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args)
181+
182+
#define PHONGO_PARSE_PARAMETERS_END() \
183+
ZEND_PARSE_PARAMETERS_END_EX( \
184+
zend_restore_error_handling(&error_handling); \
185+
return ); \
186+
zend_restore_error_handling(&error_handling); \
187+
} \
188+
while (0)
189+
190+
#ifndef ZEND_PARSE_PARAMETERS_NONE
191+
#define PHONGO_PARSE_PARAMETERS_NONE() \
192+
do { \
193+
zend_error_handling error_handling; \
194+
zend_replace_error_handling( \
195+
EH_THROW, \
196+
phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), \
197+
&error_handling); \
198+
if (zend_parse_parameters_none() == FAILURE) { \
199+
zend_restore_error_handling(&error_handling); \
200+
return; \
201+
} \
202+
zend_restore_error_handling(&error_handling); \
203+
} while (0)
204+
#else
205+
#define PHONGO_PARSE_PARAMETERS_NONE() \
206+
do { \
207+
zend_error_handling error_handling; \
208+
zend_replace_error_handling( \
209+
EH_THROW, \
210+
phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), \
211+
&error_handling); \
212+
if (UNEXPECTED(ZEND_NUM_ARGS() != 0)) { \
213+
zend_wrong_parameters_none_error(); \
214+
zend_restore_error_handling(&error_handling); \
215+
return; \
216+
} \
217+
zend_restore_error_handling(&error_handling); \
218+
} while (0)
219+
#endif
220+
172221
void phongo_add_exception_prop(const char* prop, int prop_len, zval* value);
173222
zend_bool php_phongo_zend_hash_apply_protection_begin(HashTable* ht);
174223
zend_bool php_phongo_zend_hash_apply_protection_end(HashTable* ht);

php_phongo.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2833,6 +2833,33 @@ static mongoc_client_t* php_phongo_find_persistent_client(const char* hash, size
28332833
return NULL;
28342834
}
28352835

2836+
static bool phongo_manager_set_serverapi_opts(php_phongo_manager_t* manager, zval* driverOptions) /* {{{ */
2837+
{
2838+
zval* zServerApi;
2839+
php_phongo_serverapi_t* server_api;
2840+
bson_error_t error = { 0 };
2841+
2842+
if (!driverOptions || !php_array_existsc(driverOptions, "serverApi")) {
2843+
return true;
2844+
}
2845+
2846+
zServerApi = php_array_fetch(driverOptions, "serverApi");
2847+
2848+
if (Z_TYPE_P(zServerApi) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(zServerApi), php_phongo_serverapi_ce)) {
2849+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT, "Expected \"serverApi\" driver option to be %s, %s given", ZSTR_VAL(php_phongo_serverapi_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(zServerApi));
2850+
return false;
2851+
}
2852+
2853+
server_api = Z_SERVERAPI_OBJ_P(zServerApi);
2854+
2855+
if (!mongoc_client_set_server_api(manager->client, server_api->server_api, &error)) {
2856+
phongo_throw_exception_from_bson_error_t(&error);
2857+
return false;
2858+
}
2859+
2860+
return true;
2861+
} /* }}} */
2862+
28362863
#ifdef MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION
28372864
static bool phongo_manager_set_auto_encryption_opts(php_phongo_manager_t* manager, zval* driverOptions) /* {{{ */
28382865
{
@@ -3453,6 +3480,11 @@ void phongo_manager_init(php_phongo_manager_t* manager, const char* uri_string,
34533480
goto cleanup;
34543481
}
34553482

3483+
if (!phongo_manager_set_serverapi_opts(manager, driverOptions)) {
3484+
/* Exception should already have been thrown */
3485+
goto cleanup;
3486+
}
3487+
34563488
php_phongo_set_monitoring_callbacks(manager->client);
34573489

34583490
MONGOC_DEBUG("Created client with hash: %s", manager->client_hash);
@@ -3893,6 +3925,7 @@ PHP_MINIT_FUNCTION(mongodb)
38933925
php_phongo_readconcern_init_ce(INIT_FUNC_ARGS_PASSTHRU);
38943926
php_phongo_readpreference_init_ce(INIT_FUNC_ARGS_PASSTHRU);
38953927
php_phongo_server_init_ce(INIT_FUNC_ARGS_PASSTHRU);
3928+
php_phongo_serverapi_init_ce(INIT_FUNC_ARGS_PASSTHRU);
38963929
php_phongo_session_init_ce(INIT_FUNC_ARGS_PASSTHRU);
38973930
php_phongo_writeconcern_init_ce(INIT_FUNC_ARGS_PASSTHRU);
38983931
php_phongo_writeconcernerror_init_ce(INIT_FUNC_ARGS_PASSTHRU);

php_phongo_classes.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ static inline php_phongo_server_t* php_server_fetch_object(zend_object* obj)
6363
{
6464
return (php_phongo_server_t*) ((char*) obj - XtOffsetOf(php_phongo_server_t, std));
6565
}
66+
static inline php_phongo_serverapi_t* php_serverapi_fetch_object(zend_object* obj)
67+
{
68+
return (php_phongo_serverapi_t*) ((char*) obj - XtOffsetOf(php_phongo_serverapi_t, std));
69+
}
6670
static inline php_phongo_session_t* php_session_fetch_object(zend_object* obj)
6771
{
6872
return (php_phongo_session_t*) ((char*) obj - XtOffsetOf(php_phongo_session_t, std));
@@ -157,6 +161,7 @@ static inline php_phongo_commandsucceededevent_t* php_commandsucceededevent_fetc
157161
#define Z_READCONCERN_OBJ_P(zv) (php_readconcern_fetch_object(Z_OBJ_P(zv)))
158162
#define Z_READPREFERENCE_OBJ_P(zv) (php_readpreference_fetch_object(Z_OBJ_P(zv)))
159163
#define Z_SERVER_OBJ_P(zv) (php_server_fetch_object(Z_OBJ_P(zv)))
164+
#define Z_SERVERAPI_OBJ_P(zv) (php_serverapi_fetch_object(Z_OBJ_P(zv)))
160165
#define Z_SESSION_OBJ_P(zv) (php_session_fetch_object(Z_OBJ_P(zv)))
161166
#define Z_BULKWRITE_OBJ_P(zv) (php_bulkwrite_fetch_object(Z_OBJ_P(zv)))
162167
#define Z_WRITECONCERN_OBJ_P(zv) (php_writeconcern_fetch_object(Z_OBJ_P(zv)))
@@ -189,6 +194,7 @@ static inline php_phongo_commandsucceededevent_t* php_commandsucceededevent_fetc
189194
#define Z_OBJ_READCONCERN(zo) (php_readconcern_fetch_object(zo))
190195
#define Z_OBJ_READPREFERENCE(zo) (php_readpreference_fetch_object(zo))
191196
#define Z_OBJ_SERVER(zo) (php_server_fetch_object(zo))
197+
#define Z_OBJ_SERVERAPI(zo) (php_serverapi_fetch_object(zo))
192198
#define Z_OBJ_SESSION(zo) (php_session_fetch_object(zo))
193199
#define Z_OBJ_BULKWRITE(zo) (php_bulkwrite_fetch_object(zo))
194200
#define Z_OBJ_WRITECONCERN(zo) (php_writeconcern_fetch_object(zo))
@@ -221,6 +227,7 @@ extern zend_class_entry* php_phongo_query_ce;
221227
extern zend_class_entry* php_phongo_readconcern_ce;
222228
extern zend_class_entry* php_phongo_readpreference_ce;
223229
extern zend_class_entry* php_phongo_server_ce;
230+
extern zend_class_entry* php_phongo_serverapi_ce;
224231
extern zend_class_entry* php_phongo_session_ce;
225232
extern zend_class_entry* php_phongo_bulkwrite_ce;
226233
extern zend_class_entry* php_phongo_writeconcern_ce;
@@ -318,6 +325,7 @@ extern void php_phongo_query_init_ce(INIT_FUNC_ARGS);
318325
extern void php_phongo_readconcern_init_ce(INIT_FUNC_ARGS);
319326
extern void php_phongo_readpreference_init_ce(INIT_FUNC_ARGS);
320327
extern void php_phongo_server_init_ce(INIT_FUNC_ARGS);
328+
extern void php_phongo_serverapi_init_ce(INIT_FUNC_ARGS);
321329
extern void php_phongo_session_init_ce(INIT_FUNC_ARGS);
322330
extern void php_phongo_writeconcern_init_ce(INIT_FUNC_ARGS);
323331
extern void php_phongo_writeconcernerror_init_ce(INIT_FUNC_ARGS);

php_phongo_structs.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ typedef struct {
105105
zend_object std;
106106
} php_phongo_server_t;
107107

108+
typedef struct {
109+
mongoc_server_api_t* server_api;
110+
HashTable* properties;
111+
zend_object std;
112+
} php_phongo_serverapi_t;
113+
108114
typedef struct {
109115
mongoc_client_session_t* client_session;
110116
zval manager;

scripts/convert-bson-corpus-tests.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
require_once __DIR__ . '/../tests/utils/tools.php';
3+
require_once __DIR__ . '/../tests/utils/basic.inc';
44

55
$expectedFailures = [
66
'Int64 type: -1' => 'PHP encodes integers as 32-bit if range allows',
@@ -288,7 +288,7 @@ function renderPhpt(array $params, array $expectedFailures, array $for64bitOnly)
288288
--FILE--
289289
<?php
290290
291-
require_once __DIR__ . '/../utils/tools.php';
291+
require_once __DIR__ . '/../utils/basic.inc';
292292
293293
%CODE%
294294

0 commit comments

Comments
 (0)