Skip to content

Commit c54fcb7

Browse files
committed
REBASE ME
JAVA-4936
1 parent e89fcc0 commit c54fcb7

File tree

5 files changed

+130
-22
lines changed

5 files changed

+130
-22
lines changed

driver-core/src/test/unit/com/mongodb/event/TestServerMonitorListener.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,17 @@
3939
@ThreadSafe
4040
public final class TestServerMonitorListener implements ServerMonitorListener {
4141
private final Set<Class<?>> listenableEventTypes;
42-
private final Lock lock = new ReentrantLock();
43-
private final Condition condition = lock.newCondition();
42+
private final Lock lock;
43+
private final Condition condition;
4444
private final List<Object> events;
4545

4646
public TestServerMonitorListener(final Iterable<String> listenableEventTypes) {
4747
this.listenableEventTypes = unmodifiableSet(stream(listenableEventTypes.spliterator(), false)
4848
.map(TestServerMonitorListener::nullableEventType)
4949
.filter(Objects::nonNull)
5050
.collect(Collectors.toSet()));
51+
lock = new ReentrantLock();
52+
condition = lock.newCondition();
5153
events = new ArrayList<>();
5254
}
5355

@@ -95,7 +97,15 @@ public <T> long countEvents(final Class<T> type, final Predicate<? super T> matc
9597
} finally {
9698
lock.unlock();
9799
}
100+
}
98101

102+
public List<Object> getEvents() {
103+
lock.lock();
104+
try {
105+
return new ArrayList<>(events);
106+
} finally {
107+
lock.unlock();
108+
}
99109
}
100110

101111
public static Class<?> eventType(final String eventType) {
@@ -120,12 +130,12 @@ private static Class<?> nullableEventType(final String eventType) {
120130
}
121131
}
122132

123-
private boolean listenable(final Object event) {
124-
return listenableEventTypes.contains(event.getClass());
133+
private boolean listenable(final Class<?> eventType) {
134+
return listenableEventTypes.contains(eventType);
125135
}
126136

127137
private void register(final Object event) {
128-
if (!listenable(event)) {
138+
if (!listenable(event.getClass())) {
129139
return;
130140
}
131141
lock.lock();

driver-sync/src/test/functional/com/mongodb/client/unified/ContextElement.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.mongodb.event.CommandSucceededEvent;
2424
import com.mongodb.internal.logging.LogMessage;
2525
import org.bson.BsonArray;
26+
import org.bson.BsonBoolean;
2627
import org.bson.BsonDocument;
2728
import org.bson.BsonString;
2829
import org.bson.BsonValue;
@@ -135,6 +136,40 @@ public static ContextElement ofServerMonitorEventCount(final String client, fina
135136
return new EventCountContext("Server Monitor Event Count", client, event, count);
136137
}
137138

139+
public static ContextElement ofServerMonitorEvents(final String client, final BsonArray expectedEvents, final List<?> actualEvents) {
140+
return new ContextElement() {
141+
@Override
142+
public String toString() {
143+
return "Events MatchingContext: \n"
144+
+ " client: '" + client + "'\n"
145+
+ " Expected events:\n"
146+
+ new BsonDocument("events", expectedEvents).toJson(JsonWriterSettings.builder().indent(true).build()) + "\n"
147+
+ " Actual events:\n"
148+
+ new BsonDocument("events",
149+
new BsonArray(actualEvents.stream().map(ContextElement::serverMonitorEventToDocument).collect(Collectors.toList())))
150+
.toJson(JsonWriterSettings.builder().indent(true).build())
151+
+ "\n";
152+
}
153+
154+
private BsonDocument toDocument(final Object event) {
155+
return new BsonDocument(EventMatcher.getEventType(event.getClass()),
156+
new BsonDocument("awaited", BsonBoolean.valueOf(EventMatcher.getAwaitedFromServerMonitorEvent(event))));
157+
}
158+
};
159+
}
160+
161+
public static ContextElement ofServerMonitorEvent(final BsonDocument expected, final Object actual, final int eventPosition) {
162+
return new ContextElement() {
163+
@Override
164+
public String toString() {
165+
return "Event Matching Context\n"
166+
+ " event position: " + eventPosition + "\n"
167+
+ " expected event: " + expected + "\n"
168+
+ " actual event: " + serverMonitorEventToDocument(actual) + "\n";
169+
}
170+
};
171+
}
172+
138173
private static class EventCountContext extends ContextElement {
139174

140175
private final String name;
@@ -425,4 +460,9 @@ public String toString() {
425460
private static BsonDocument connectionPoolEventToDocument(final Object event) {
426461
return new BsonDocument(event.getClass().getSimpleName(), new BsonDocument());
427462
}
463+
464+
private static BsonDocument serverMonitorEventToDocument(final Object event) {
465+
return new BsonDocument(EventMatcher.getEventType(event.getClass()),
466+
new BsonDocument("awaited", BsonBoolean.valueOf(EventMatcher.getAwaitedFromServerMonitorEvent(event))));
467+
}
428468
}

driver-sync/src/test/functional/com/mongodb/client/unified/Entities.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.mongodb.ReadConcernLevel;
2424
import com.mongodb.ServerApi;
2525
import com.mongodb.ServerApiVersion;
26+
import com.mongodb.connection.ServerMonitoringMode;
2627
import com.mongodb.event.TestServerMonitorListener;
2728
import com.mongodb.internal.connection.TestClusterListener;
2829
import com.mongodb.logging.TestLoggingInterceptor;
@@ -506,6 +507,10 @@ private void initClient(final BsonDocument entity, final String id,
506507
case "appName":
507508
clientSettingsBuilder.applicationName(value.asString().getValue());
508509
break;
510+
case "serverMonitoringMode":
511+
clientSettingsBuilder.applyToServerSettings(builder -> builder.serverMonitoringMode(
512+
ServerMonitoringMode.fromString(value.asString().getValue())));
513+
break;
509514
default:
510515
throw new UnsupportedOperationException("Unsupported uri option: " + key);
511516
}

driver-sync/src/test/functional/com/mongodb/client/unified/EventMatcher.java

Lines changed: 64 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import com.mongodb.internal.connection.TestConnectionPoolListener;
3939
import com.mongodb.internal.connection.TestServerListener;
4040
import com.mongodb.lang.NonNull;
41+
import com.mongodb.lang.Nullable;
4142
import org.bson.BsonArray;
4243
import org.bson.BsonDocument;
4344
import org.bson.types.ObjectId;
@@ -295,7 +296,7 @@ public <T> void waitForServerMonitorEvents(final String client, final Class<T> e
295296
BsonDocument expectedEventContents = getEventContents(expectedEvent);
296297
try {
297298
serverMonitorListener.waitForEvents(expectedEventType,
298-
event -> serverMonitorEventMatches(expectedEventContents, event), count, Duration.ofSeconds(10));
299+
event -> serverMonitorEventMatches(expectedEventContents, event, null), count, Duration.ofSeconds(10));
299300
context.pop();
300301
} catch (InterruptedException e) {
301302
throw new RuntimeException(e);
@@ -308,11 +309,37 @@ public <T> void assertServerMonitorEventCount(final String client, final Class<T
308309
final int count, final TestServerMonitorListener serverMonitorListener) {
309310
BsonDocument expectedEventContents = getEventContents(expectedEvent);
310311
context.push(ContextElement.ofServerMonitorEventCount(client, expectedEvent, count));
311-
long matchCount = serverMonitorListener.countEvents(expectedEventType, event -> serverMonitorEventMatches(expectedEventContents, event));
312+
long matchCount = serverMonitorListener.countEvents(expectedEventType, event ->
313+
serverMonitorEventMatches(expectedEventContents, event, null));
312314
assertEquals(context.getMessage("Expected server monitor event counts to match"), count, matchCount);
313315
context.pop();
314316
}
315317

318+
public void assertServerMonitorEventsEquality(
319+
final String client,
320+
final boolean ignoreExtraEvents,
321+
final BsonArray expectedEventDocuments,
322+
final List<?> events) {
323+
context.push(ContextElement.ofServerMonitorEvents(client, expectedEventDocuments, events));
324+
if (ignoreExtraEvents) {
325+
assertTrue(context.getMessage("Number of events must be greater than or equal to the expected number of events"),
326+
events.size() >= expectedEventDocuments.size());
327+
} else {
328+
assertEquals(context.getMessage("Number of events must be the same"), expectedEventDocuments.size(), events.size());
329+
}
330+
for (int i = 0; i < expectedEventDocuments.size(); i++) {
331+
Object actualEvent = events.get(i);
332+
BsonDocument expectedEventDocument = expectedEventDocuments.get(i).asDocument();
333+
String expectedEventType = expectedEventDocument.getFirstKey();
334+
context.push(ContextElement.ofServerMonitorEvent(expectedEventDocument, actualEvent, i));
335+
assertEquals(context.getMessage("Expected event type to match"), expectedEventType, getEventType(actualEvent.getClass()));
336+
BsonDocument expectedEventContents = expectedEventDocument.getDocument(expectedEventType);
337+
serverMonitorEventMatches(expectedEventContents, actualEvent, context);
338+
context.pop();
339+
}
340+
context.pop();
341+
}
342+
316343
@NonNull
317344
private BsonDocument getEventContents(final BsonDocument expectedEvent) {
318345
HashSet<String> supportedEventTypes = new HashSet<>(asList(
@@ -364,30 +391,52 @@ private static boolean clusterDescriptionChangedEventMatches(final BsonDocument
364391
return true;
365392
}
366393

367-
private static <T> boolean serverMonitorEventMatches(final BsonDocument expectedEventContents, final T event) {
394+
/**
395+
* @param context Not {@code null} iff mismatch must result in an error, that is, this method works as an assertion.
396+
*/
397+
private static <T> boolean serverMonitorEventMatches(
398+
final BsonDocument expectedEventContents,
399+
final T event,
400+
@Nullable final AssertionContext context) {
401+
if (expectedEventContents.size() > 1) {
402+
throw new UnsupportedOperationException("Matching for the following event is not implemented " + expectedEventContents.toJson());
403+
}
368404
if (expectedEventContents.containsKey("awaited")) {
369405
boolean expectedAwaited = expectedEventContents.getBoolean("awaited").getValue();
370-
boolean actualAwaited;
371-
if (event instanceof ServerHeartbeatStartedEvent) {
372-
actualAwaited = ((ServerHeartbeatStartedEvent) event).isAwaited();
373-
} else if (event instanceof ServerHeartbeatSucceededEvent) {
374-
actualAwaited = ((ServerHeartbeatSucceededEvent) event).isAwaited();
375-
} else if (event instanceof ServerHeartbeatFailedEvent) {
376-
actualAwaited = ((ServerHeartbeatFailedEvent) event).isAwaited();
377-
} else {
378-
throw Assertions.fail(event.toString());
406+
boolean actualAwaited = getAwaitedFromServerMonitorEvent(event);
407+
boolean awaitedMatches = expectedAwaited == actualAwaited;
408+
if (context != null) {
409+
assertTrue(context.getMessage("Expected `awaited` to match"), awaitedMatches);
379410
}
380-
return expectedAwaited == actualAwaited;
411+
return awaitedMatches;
381412
}
382413
return true;
383414
}
384415

385-
private static String getEventType(final Class<?> eventClass) {
416+
static boolean getAwaitedFromServerMonitorEvent(final Object event) {
417+
if (event instanceof ServerHeartbeatStartedEvent) {
418+
return ((ServerHeartbeatStartedEvent) event).isAwaited();
419+
} else if (event instanceof ServerHeartbeatSucceededEvent) {
420+
return ((ServerHeartbeatSucceededEvent) event).isAwaited();
421+
} else if (event instanceof ServerHeartbeatFailedEvent) {
422+
return ((ServerHeartbeatFailedEvent) event).isAwaited();
423+
} else {
424+
throw Assertions.fail(event.toString());
425+
}
426+
}
427+
428+
static String getEventType(final Class<?> eventClass) {
386429
String eventClassName = eventClass.getSimpleName();
387430
if (eventClassName.startsWith("ConnectionPool")) {
388431
return eventClassName.replace("ConnectionPool", "pool");
389-
} else {
432+
} else if (eventClassName.startsWith("Connection")) {
390433
return eventClassName.replace("Connection", "connection");
434+
} else if (eventClassName.startsWith("ServerHeartbeat")) {
435+
StringBuilder eventTypeBuilder = new StringBuilder(eventClassName);
436+
eventTypeBuilder.setCharAt(0, Character.toLowerCase(eventTypeBuilder.charAt(0)));
437+
return eventTypeBuilder.toString();
438+
} else {
439+
throw new UnsupportedOperationException(eventClassName);
391440
}
392441
}
393442

driver-sync/src/test/functional/com/mongodb/client/unified/UnifiedTest.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,14 +269,18 @@ private void compareEvents(final UnifiedTestContext context, final BsonDocument
269269
String client = curClientEvents.getString("client").getValue();
270270
boolean ignoreExtraEvents = curClientEvents.getBoolean("ignoreExtraEvents", BsonBoolean.FALSE).getValue();
271271
String eventType = curClientEvents.getString("eventType", new BsonString("command")).getValue();
272+
BsonArray expectedEvents = curClientEvents.getArray("events");
272273
if (eventType.equals("command")) {
273274
TestCommandListener listener = entities.getClientCommandListener(client);
274-
context.getEventMatcher().assertCommandEventsEquality(client, ignoreExtraEvents, curClientEvents.getArray("events"),
275+
context.getEventMatcher().assertCommandEventsEquality(client, ignoreExtraEvents, expectedEvents,
275276
listener.getEvents());
276277
} else if (eventType.equals("cmap")) {
277278
TestConnectionPoolListener listener = entities.getConnectionPoolListener(client);
278-
context.getEventMatcher().assertConnectionPoolEventsEquality(client, ignoreExtraEvents, curClientEvents.getArray("events"),
279+
context.getEventMatcher().assertConnectionPoolEventsEquality(client, ignoreExtraEvents, expectedEvents,
279280
listener.getEvents());
281+
} else if (eventType.equals("sdam")) {
282+
TestServerMonitorListener listener = entities.getServerMonitorListener(client);
283+
context.getEventMatcher().assertServerMonitorEventsEquality(client, ignoreExtraEvents, expectedEvents, listener.getEvents());
280284
} else {
281285
throw new UnsupportedOperationException("Unexpected event type: " + eventType);
282286
}

0 commit comments

Comments
 (0)