11/*
2- * Copyright (c) 2015 MongoDB, Inc.
2+ * Copyright 2015-2016 MongoDB, Inc.
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
3232import org .bson .BsonArray ;
3333import org .bson .BsonBoolean ;
3434import org .bson .BsonDocument ;
35+ import org .bson .BsonDocumentWriter ;
3536import org .bson .BsonDouble ;
3637import org .bson .BsonInt32 ;
3738import org .bson .BsonInt64 ;
3839import org .bson .BsonString ;
3940import org .bson .BsonValue ;
4041import org .bson .Document ;
42+ import org .bson .codecs .BsonDocumentCodec ;
43+ import org .bson .codecs .BsonValueCodecProvider ;
44+ import org .bson .codecs .Codec ;
4145import org .bson .codecs .DocumentCodec ;
46+ import org .bson .codecs .EncoderContext ;
47+ import org .bson .codecs .configuration .CodecProvider ;
48+ import org .bson .codecs .configuration .CodecRegistries ;
49+ import org .bson .codecs .configuration .CodecRegistry ;
4250import org .junit .AfterClass ;
4351import org .junit .Before ;
4452import org .junit .BeforeClass ;
6977// See https://github.com/mongodb/specifications/tree/master/source/command-monitoring/tests
7078@ RunWith (Parameterized .class )
7179public class CommandMonitoringTest {
80+ private static final CodecRegistry CODEC_REGISTRY_HACK = CodecRegistries .fromProviders (new BsonValueCodecProvider (),
81+ new CodecProvider () {
82+ @ Override
83+ @ SuppressWarnings ("unchecked" )
84+ public <T > Codec <T > get (final Class <T > clazz , final CodecRegistry registry ) {
85+ // Use BsonDocumentCodec even for a private sub-class of BsonDocument
86+ if (BsonDocument .class .isAssignableFrom (clazz )) {
87+ return (Codec <T >) new BsonDocumentCodec (registry );
88+ }
89+ return null ;
90+ }
91+ });
92+
7293 private static MongoClient mongoClient ;
7394 private static TestCommandListener commandListener ;
7495 private final String filename ;
@@ -210,43 +231,48 @@ private CommandSucceededEvent massageExpectedCommandSucceededEvent(final Command
210231 }
211232
212233 private CommandSucceededEvent massageActualCommandSucceededEvent (final CommandSucceededEvent actual ) {
234+ BsonDocument response = getWritableCloneOfCommand (actual .getResponse ());
235+
213236 // massage numbers that are the wrong BSON type
214- actual . getResponse (). put ("ok" , new BsonDouble (actual . getResponse () .getNumber ("ok" ).doubleValue ()));
215- if (actual . getResponse () .containsKey ("n" )) {
216- actual . getResponse (). put ("n" , new BsonInt32 (actual . getResponse () .getNumber ("n" ).intValue ()));
237+ response . put ("ok" , new BsonDouble (response .getNumber ("ok" ).doubleValue ()));
238+ if (response .containsKey ("n" )) {
239+ response . put ("n" , new BsonInt32 (response .getNumber ("n" ).intValue ()));
217240 }
218241
219242 if (actual .getCommandName ().equals ("find" ) || actual .getCommandName ().equals ("getMore" )) {
220- if (actual . getResponse () .containsKey ("cursor" )) {
221- if (actual . getResponse () .getDocument ("cursor" ).containsKey ("id" )
222- && !actual . getResponse () .getDocument ("cursor" ).getInt64 ("id" ).equals (new BsonInt64 (0 ))) {
223- actual . getResponse () .getDocument ("cursor" ).put ("id" , new BsonInt64 (42 ));
243+ if (response .containsKey ("cursor" )) {
244+ if (response .getDocument ("cursor" ).containsKey ("id" )
245+ && !response .getDocument ("cursor" ).getInt64 ("id" ).equals (new BsonInt64 (0 ))) {
246+ response .getDocument ("cursor" ).put ("id" , new BsonInt64 (42 ));
224247 }
225248 }
226249 } else if (actual .getCommandName ().equals ("killCursors" )) {
227- actual . getResponse () .getArray ("cursorsUnknown" ).set (0 , new BsonInt64 (42 ));
250+ response .getArray ("cursorsUnknown" ).set (0 , new BsonInt64 (42 ));
228251 } else if (isWriteCommand (actual .getCommandName ())) {
229- if (actual . getResponse () .containsKey ("writeErrors" )) {
230- for (Iterator <BsonValue > iter = actual . getResponse () .getArray ("writeErrors" ).iterator (); iter .hasNext ();) {
252+ if (response .containsKey ("writeErrors" )) {
253+ for (Iterator <BsonValue > iter = response .getArray ("writeErrors" ).iterator (); iter .hasNext ();) {
231254 BsonDocument cur = iter .next ().asDocument ();
232255 cur .put ("code" , new BsonInt32 (42 ));
233256 cur .put ("errmsg" , new BsonString ("" ));
234257 }
235258 }
236259 if (actual .getCommandName ().equals ("update" )) {
237- actual . getResponse () .remove ("nModified" );
260+ response .remove ("nModified" );
238261 }
239262 }
240- return actual ;
263+ return new CommandSucceededEvent (actual .getRequestId (), actual .getConnectionDescription (), actual .getCommandName (), response ,
264+ actual .getElapsedTime (TimeUnit .NANOSECONDS ));
241265 }
242266
243267 private boolean isWriteCommand (final String commandName ) {
244268 return asList ("insert" , "update" , "delete" ).contains (commandName );
245269 }
246270
247271 private CommandStartedEvent massageActualCommandStartedEvent (final CommandStartedEvent actual ) {
272+ BsonDocument command = getWritableCloneOfCommand (actual .getCommand ());
273+
248274 if (actual .getCommandName ().equals ("update" )) {
249- for (Iterator <BsonValue > iter = actual . getCommand () .getArray ("updates" ).iterator (); iter .hasNext ();) {
275+ for (Iterator <BsonValue > iter = command .getArray ("updates" ).iterator (); iter .hasNext ();) {
250276 BsonDocument curUpdate = iter .next ().asDocument ();
251277 if (!curUpdate .containsKey ("multi" )) {
252278 curUpdate .put ("multi" , BsonBoolean .FALSE );
@@ -256,12 +282,13 @@ private CommandStartedEvent massageActualCommandStartedEvent(final CommandStarte
256282 }
257283 }
258284 } else if (actual .getCommandName ().equals ("getMore" )) {
259- actual . getCommand () .put ("getMore" , new BsonInt64 (42 ));
285+ command .put ("getMore" , new BsonInt64 (42 ));
260286 } else if (actual .getCommandName ().equals ("killCursors" )) {
261- actual . getCommand () .getArray ("cursors" ).set (0 , new BsonInt64 (42 ));
287+ command .getArray ("cursors" ).set (0 , new BsonInt64 (42 ));
262288 }
263289
264- return actual ;
290+ return new CommandStartedEvent (actual .getRequestId (), actual .getConnectionDescription (), actual .getDatabaseName (),
291+ actual .getCommandName (), command );
265292 }
266293
267294 private void executeOperation () {
@@ -298,6 +325,15 @@ private List<CommandEvent> getExpectedEvents(final BsonArray expectedEventDocume
298325 return expectedEvents ;
299326 }
300327
328+
329+ private BsonDocument getWritableCloneOfCommand (final BsonDocument original ) {
330+ BsonDocument clone = new BsonDocument ();
331+ BsonDocumentWriter writer = new BsonDocumentWriter (clone );
332+ new BsonDocumentCodec (CODEC_REGISTRY_HACK ).encode (writer , original , EncoderContext .builder ().build ());
333+ return clone ;
334+ }
335+
336+
301337 @ Parameterized .Parameters (name = "{1}" )
302338 public static Collection <Object []> data () throws URISyntaxException , IOException {
303339 List <Object []> data = new ArrayList <Object []>();
0 commit comments