@@ -1095,6 +1095,97 @@ typedef struct {
1095
1095
int agg_count ;
1096
1096
} array_started_ctx_t ;
1097
1097
1098
+ static void
1099
+ _accepts_array_started (const mongoc_apm_command_started_t * event )
1100
+ {
1101
+ const bson_t * cmd = mongoc_apm_command_started_get_command (event );
1102
+ const char * cmd_name = mongoc_apm_command_started_get_command_name (event );
1103
+ array_started_ctx_t * ctx =
1104
+ (array_started_ctx_t * ) mongoc_apm_command_started_get_context (event );
1105
+ if (strcmp (cmd_name , "aggregate" ) != 0 ) {
1106
+ return ;
1107
+ }
1108
+ ctx -> agg_count ++ ;
1109
+ ASSERT_MATCH (cmd , ctx -> pattern );
1110
+ }
1111
+
1112
+ /* Test that watch accepts an array document {0: {}, 1: {}} as the pipeline,
1113
+ * similar to mongoc_collection_aggregate */
1114
+ static void
1115
+ test_change_stream_accepts_array (void * test_ctx )
1116
+ {
1117
+ mongoc_client_t * client = test_framework_client_new ();
1118
+ mongoc_apm_callbacks_t * callbacks = mongoc_apm_callbacks_new ();
1119
+ array_started_ctx_t ctx = {0 };
1120
+ mongoc_collection_t * coll ;
1121
+ mongoc_change_stream_t * stream ;
1122
+ const bson_t * bson ;
1123
+ bson_error_t err ;
1124
+ bson_t * opts =
1125
+ tmp_bson ("{'maxAwaitTimeMS': 1}" ); /* to speed up the test. */
1126
+
1127
+ mongoc_client_set_error_api (client , MONGOC_ERROR_API_VERSION_2 );
1128
+ /* set up apm callbacks to listen for the agg commands. */
1129
+ ctx .pattern =
1130
+ bson_strdup ("{'aggregate': 'coll', 'pipeline': [ {'$changeStream': {}}, "
1131
+ "{'$match': {'x': 1}}, {'$project': {'x': 1}}]}" );
1132
+ mongoc_apm_set_command_started_cb (callbacks , _accepts_array_started );
1133
+ mongoc_client_set_apm_callbacks (client , callbacks , & ctx );
1134
+ coll = mongoc_client_get_collection (client , "db" , "coll" );
1135
+ ASSERT_OR_PRINT (
1136
+ mongoc_collection_insert_one (coll , tmp_bson (NULL ), NULL , NULL , & err ),
1137
+ err );
1138
+ /* try starting a change stream with a { "pipeline": [...] } argument */
1139
+ stream = mongoc_collection_watch (
1140
+ coll ,
1141
+ tmp_bson ("{'pipeline': [{'$match': {'x': 1}}, {'$project': {'x': 1}}]}" ),
1142
+ opts );
1143
+ (void ) mongoc_change_stream_next (stream , & bson );
1144
+ ASSERT_OR_PRINT (!mongoc_change_stream_error_document (stream , & err , & bson ),
1145
+ err );
1146
+ ASSERT_CMPINT32 (ctx .agg_count , = = , 1 );
1147
+ mongoc_change_stream_destroy (stream );
1148
+ /* try with an array like document. */
1149
+ stream = mongoc_collection_watch (
1150
+ coll ,
1151
+ tmp_bson ("{'0': {'$match': {'x': 1}}, '1': {'$project': {'x': 1}}}" ),
1152
+ opts );
1153
+ (void ) mongoc_change_stream_next (stream , & bson );
1154
+ ASSERT_OR_PRINT (!mongoc_change_stream_error_document (stream , & err , & bson ),
1155
+ err );
1156
+ ASSERT_CMPINT32 (ctx .agg_count , = = , 2 );
1157
+ mongoc_change_stream_destroy (stream );
1158
+ /* try with malformed { "pipeline": [...] } argument. */
1159
+ bson_free (ctx .pattern );
1160
+ ctx .pattern = bson_strdup (
1161
+ "{'aggregate': 'coll', 'pipeline': [ {'$changeStream': {}}, 42 ]}" );
1162
+ stream =
1163
+ mongoc_collection_watch (coll , tmp_bson ("{'pipeline': [42] }" ), NULL );
1164
+ (void ) mongoc_change_stream_next (stream , & bson );
1165
+ BSON_ASSERT (mongoc_change_stream_error_document (stream , & err , & bson ));
1166
+ ASSERT_ERROR_CONTAINS (
1167
+ err ,
1168
+ MONGOC_ERROR_SERVER ,
1169
+ 14 ,
1170
+ "Each element of the 'pipeline' array must be an object" );
1171
+ ASSERT_CMPINT32 (ctx .agg_count , = = , 3 );
1172
+ mongoc_change_stream_destroy (stream );
1173
+ /* try with malformed array doc argument. */
1174
+ stream = mongoc_collection_watch (coll , tmp_bson ("{'0': 42 }" ), NULL );
1175
+ (void ) mongoc_change_stream_next (stream , & bson );
1176
+ BSON_ASSERT (mongoc_change_stream_error_document (stream , & err , & bson ));
1177
+ ASSERT_ERROR_CONTAINS (
1178
+ err ,
1179
+ MONGOC_ERROR_SERVER ,
1180
+ 14 ,
1181
+ "Each element of the 'pipeline' array must be an object" );
1182
+ ASSERT_CMPINT32 (ctx .agg_count , = = , 4 );
1183
+ mongoc_change_stream_destroy (stream );
1184
+ bson_free (ctx .pattern );
1185
+ mongoc_apm_callbacks_destroy (callbacks );
1186
+ mongoc_collection_destroy (coll );
1187
+ mongoc_client_destroy (client );
1188
+ }
1098
1189
1099
1190
void
1100
1191
test_change_stream_install (TestSuite * suite )
@@ -1165,4 +1256,11 @@ test_change_stream_install (TestSuite *suite)
1165
1256
NULL ,
1166
1257
NULL ,
1167
1258
test_framework_skip_if_not_rs_version_6 );
1259
+
1260
+ TestSuite_AddFull (suite ,
1261
+ "/change_stream/accepts_array" ,
1262
+ test_change_stream_accepts_array ,
1263
+ NULL ,
1264
+ NULL ,
1265
+ test_framework_skip_if_not_rs_version_6 );
1168
1266
}
0 commit comments