Skip to content

Commit c9cfd8e

Browse files
authored
Refactor tests, credential code (#1102)
Refactoring for: JAVA-4757
1 parent 15911e0 commit c9cfd8e

File tree

6 files changed

+121
-85
lines changed

6 files changed

+121
-85
lines changed

bson/src/test/unit/org/bson/codecs/pojo/PojoTestCase.java

Lines changed: 7 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -70,17 +70,13 @@
7070
import java.util.Map;
7171
import java.util.Set;
7272
import java.util.concurrent.ConcurrentHashMap;
73-
import java.util.concurrent.CountDownLatch;
74-
import java.util.concurrent.ExecutorService;
75-
import java.util.concurrent.Executors;
7673

77-
import static java.lang.String.format;
7874
import static java.util.Arrays.asList;
7975
import static java.util.Collections.singletonList;
8076
import static org.bson.codecs.configuration.CodecRegistries.fromProviders;
8177
import static org.bson.codecs.pojo.Conventions.DEFAULT_CONVENTIONS;
8278
import static org.junit.Assert.assertEquals;
83-
import static org.junit.Assert.assertTrue;
79+
import static util.ThreadTestHelpers.executeAll;
8480

8581
abstract class PojoTestCase {
8682

@@ -97,34 +93,12 @@ <T> void roundTrip(final PojoCodecProvider.Builder builder, final T value, final
9793

9894
<T> void threadedRoundTrip(final PojoCodecProvider.Builder builder, final T value, final String json) {
9995
int numberOfThreads = 5;
100-
ExecutorService service = null;
101-
try {
102-
service = Executors.newFixedThreadPool(10);
103-
CountDownLatch latch = new CountDownLatch(numberOfThreads);
104-
List<String> errors = new ArrayList<>();
105-
CodecRegistry codecRegistry = getCodecRegistry(builder);
106-
for (int i = 0; i < numberOfThreads; i++) {
107-
service.submit(() -> {
108-
try {
109-
encodesTo(codecRegistry, value, json);
110-
decodesTo(codecRegistry, json, value);
111-
} catch (Exception e) {
112-
errors.add(e instanceof NullPointerException ? "NPE: " + e.getStackTrace()[0] : e.getMessage());
113-
}
114-
latch.countDown();
115-
});
116-
}
117-
try {
118-
latch.await();
119-
} catch (InterruptedException e) {
120-
// Ignore
121-
}
122-
assertTrue(format("Errors encountered: [%s]", String.join(",", errors)), errors.isEmpty());
123-
} finally {
124-
if (service != null) {
125-
service.shutdown();
126-
}
127-
}
96+
CodecRegistry codecRegistry = getCodecRegistry(builder);
97+
98+
executeAll(numberOfThreads, () -> {
99+
encodesTo(codecRegistry, value, json);
100+
decodesTo(codecRegistry, json, value);
101+
});
128102
}
129103

130104
<T> void roundTrip(final CodecRegistry registry, final T value, final String json) {
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright 2008-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package util;
18+
19+
import org.opentest4j.MultipleFailuresError;
20+
21+
import java.util.ArrayList;
22+
import java.util.Collections;
23+
import java.util.List;
24+
import java.util.concurrent.CountDownLatch;
25+
import java.util.concurrent.ExecutorService;
26+
import java.util.concurrent.Executors;
27+
28+
public final class ThreadTestHelpers {
29+
30+
private ThreadTestHelpers() {
31+
}
32+
33+
public static void executeAll(final int nThreads, final Runnable c) {
34+
ExecutorService service = null;
35+
try {
36+
service = Executors.newFixedThreadPool(nThreads);
37+
CountDownLatch latch = new CountDownLatch(nThreads);
38+
List<Throwable> failures = Collections.synchronizedList(new ArrayList<>());
39+
for (int i = 0; i < nThreads; i++) {
40+
service.submit(() -> {
41+
try {
42+
c.run();
43+
} catch (Throwable e) {
44+
failures.add(e);
45+
} finally {
46+
latch.countDown();
47+
}
48+
});
49+
}
50+
try {
51+
latch.await();
52+
} catch (InterruptedException e) {
53+
Thread.currentThread().interrupt();
54+
throw new RuntimeException(e);
55+
}
56+
if (!failures.isEmpty()) {
57+
MultipleFailuresError multipleFailuresError = new MultipleFailuresError("Failed to execute all", failures);
58+
failures.forEach(multipleFailuresError::addSuppressed);
59+
throw multipleFailuresError;
60+
}
61+
} finally {
62+
if (service != null) {
63+
service.shutdown();
64+
}
65+
}
66+
}
67+
}

driver-core/src/main/com/mongodb/MongoCredential.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,8 @@ public MongoCredential withMechanism(final AuthenticationMechanism mechanism) {
369369

370370
MongoCredential(@Nullable final AuthenticationMechanism mechanism, @Nullable final String userName, final String source,
371371
@Nullable final char[] password, final Map<String, Object> mechanismProperties) {
372-
if (mechanism != MONGODB_X509 && mechanism != MONGODB_AWS && userName == null) {
372+
373+
if (userName == null && !Arrays.asList(MONGODB_X509, MONGODB_AWS).contains(mechanism)) {
373374
throw new IllegalArgumentException("username can not be null");
374375
}
375376

@@ -399,7 +400,6 @@ public MongoCredential withMechanism(final AuthenticationMechanism mechanism) {
399400

400401
private boolean mechanismRequiresPassword(@Nullable final AuthenticationMechanism mechanism) {
401402
return mechanism == PLAIN || mechanism == SCRAM_SHA_1 || mechanism == SCRAM_SHA_256;
402-
403403
}
404404

405405
/**
@@ -411,14 +411,14 @@ private boolean mechanismRequiresPassword(@Nullable final AuthenticationMechanis
411411
* @param <T> the mechanism property type
412412
*/
413413
<T> MongoCredential(final MongoCredential from, final String mechanismPropertyKey, final T mechanismPropertyValue) {
414-
notNull("mechanismPropertyKey", mechanismPropertyKey);
415-
416-
this.mechanism = from.mechanism;
417-
this.userName = from.userName;
418-
this.source = from.source;
419-
this.password = from.password;
420-
this.mechanismProperties = new HashMap<>(from.mechanismProperties);
421-
this.mechanismProperties.put(mechanismPropertyKey.toLowerCase(), mechanismPropertyValue);
414+
this(from.mechanism, from.userName, from.source, from.password, mapWith(from.mechanismProperties, notNull(
415+
"mechanismPropertyKey", mechanismPropertyKey).toLowerCase(), mechanismPropertyValue));
416+
}
417+
418+
private static <T> Map<String, Object> mapWith(final Map<String, Object> map, final String key, final T value) {
419+
HashMap<String, Object> result = new HashMap<>(map);
420+
result.put(key, value);
421+
return result;
422422
}
423423

424424
/**

driver-core/src/main/com/mongodb/internal/connection/AwsAuthenticator.java

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,7 @@ public byte[] evaluateChallenge(final byte[] challenge) throws SaslException {
105105
step++;
106106
if (step == 0) {
107107
return computeClientFirstMessage();
108-
}
109-
if (step == 1) {
108+
} else if (step == 1) {
110109
return computeClientFinalMessage(challenge);
111110
} else {
112111
throw new SaslException(format("Too many steps involved in the %s negotiation.", getMechanismName()));
@@ -207,14 +206,14 @@ private AwsCredential createAwsCredential() {
207206
}
208207
return awsCredential;
209208
}
209+
}
210210

211-
private byte[] toBson(final BsonDocument document) {
212-
byte[] bytes;
213-
BasicOutputBuffer buffer = new BasicOutputBuffer();
214-
new BsonDocumentCodec().encode(new BsonBinaryWriter(buffer), document, EncoderContext.builder().build());
215-
bytes = new byte[buffer.size()];
216-
System.arraycopy(buffer.getInternalBuffer(), 0, bytes, 0, buffer.getSize());
217-
return bytes;
218-
}
211+
private static byte[] toBson(final BsonDocument document) {
212+
byte[] bytes;
213+
BasicOutputBuffer buffer = new BasicOutputBuffer();
214+
new BsonDocumentCodec().encode(new BsonBinaryWriter(buffer), document, EncoderContext.builder().build());
215+
bytes = new byte[buffer.size()];
216+
System.arraycopy(buffer.getInternalBuffer(), 0, bytes, 0, buffer.getSize());
217+
return bytes;
219218
}
220219
}

driver-core/src/main/com/mongodb/internal/connection/MongoCredentialWithCache.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public MongoCredentialWithCache(final MongoCredential credential) {
3636
this(credential, null);
3737
}
3838

39-
public MongoCredentialWithCache(final MongoCredential credential, @Nullable final Cache cache) {
39+
private MongoCredentialWithCache(final MongoCredential credential, @Nullable final Cache cache) {
4040
this.credential = credential;
4141
this.cache = cache != null ? cache : new Cache();
4242
}

driver-core/src/test/unit/com/mongodb/AuthConnectionStringTest.java

Lines changed: 27 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import junit.framework.TestCase;
2020
import org.bson.BsonDocument;
21+
import org.bson.BsonNull;
2122
import org.bson.BsonValue;
2223
import org.junit.Test;
2324
import org.junit.runner.RunWith;
@@ -34,15 +35,11 @@
3435
// See https://github.com/mongodb/specifications/tree/master/source/auth/tests
3536
@RunWith(Parameterized.class)
3637
public class AuthConnectionStringTest extends TestCase {
37-
private final String filename;
38-
private final String description;
3938
private final String input;
4039
private final BsonDocument definition;
4140

4241
public AuthConnectionStringTest(final String filename, final String description, final String input,
4342
final BsonDocument definition) {
44-
this.filename = filename;
45-
this.description = description;
4643
this.input = input;
4744
this.definition = definition;
4845
}
@@ -71,27 +68,18 @@ public static Collection<Object[]> data() throws URISyntaxException, IOException
7168

7269
private void testInvalidUris() {
7370
Throwable expectedError = null;
74-
7571
try {
76-
new ConnectionString(input);
72+
new ConnectionString(input).getCredential();
7773
} catch (Throwable t) {
7874
expectedError = t;
7975
}
80-
81-
assertTrue(String.format("Connection string '%s' should have throw an exception", input),
76+
assertTrue(String.format("Connection string '%s' should have thrown an exception. Instead, %s", input, expectedError),
8277
expectedError instanceof IllegalArgumentException);
8378
}
8479

8580
private void testValidUris() {
86-
ConnectionString connectionString = null;
87-
88-
try {
89-
connectionString = new ConnectionString(input);
90-
} catch (Throwable t) {
91-
fail(String.format("Connection string '%s' should not have throw an exception: %s", input, t));
92-
}
81+
MongoCredential credential = new ConnectionString(input).getCredential();
9382

94-
MongoCredential credential = connectionString.getCredential();
9583
if (credential != null) {
9684
assertString("credential.source", credential.getSource());
9785
assertString("credential.username", credential.getUserName());
@@ -104,6 +92,10 @@ private void testValidUris() {
10492
}
10593

10694
assertMechanism("credential.mechanism", credential.getMechanism());
95+
} else {
96+
if (!getExpectedValue("credential").equals(BsonNull.VALUE)) {
97+
fail(String.format("Connection string '%s' should produce credentials", input));
98+
}
10799
}
108100
}
109101

@@ -133,23 +125,27 @@ private void assertMechanism(final String key, final String actual) {
133125

134126
private void assertMechanismProperties(final MongoCredential credential) {
135127
BsonValue expected = getExpectedValue("credential.mechanism_properties");
136-
137-
if (!expected.isNull()) {
138-
BsonDocument document = expected.asDocument();
139-
for (String key : document.keySet()) {
140-
if (document.get(key).isString()) {
141-
String expectedValue = document.getString(key).getValue();
142-
143-
// If the mechanism is "GSSAPI", the default SERVICE_NAME, which is stated as "mongodb" in the specification,
144-
// is set to null in the driver.
145-
if (credential.getMechanism().equals("GSSAPI") && key.equals("SERVICE_NAME") && expectedValue.equals("mongodb")) {
146-
assertNull(credential.getMechanismProperty(key, null));
147-
} else {
148-
assertEquals(expectedValue, credential.getMechanismProperty(key, null));
149-
}
128+
if (expected.isNull()) {
129+
return;
130+
}
131+
BsonDocument document = expected.asDocument();
132+
for (String key : document.keySet()) {
133+
Object actualMechanismProperty = credential.getMechanismProperty(key, null);
134+
if (document.get(key).isString()) {
135+
String expectedValue = document.getString(key).getValue();
136+
// If the mechanism is "GSSAPI", the default SERVICE_NAME, which is stated as "mongodb" in the specification,
137+
// is set to null in the driver.
138+
if (credential.getMechanism().equals("GSSAPI") && key.equals("SERVICE_NAME") && expectedValue.equals("mongodb")) {
139+
assertNull(actualMechanismProperty);
150140
} else {
151-
assertEquals(document.getBoolean(key).getValue(), credential.getMechanismProperty(key, (Boolean) null).booleanValue());
141+
assertEquals(expectedValue, actualMechanismProperty);
152142
}
143+
} else if ((document.get(key).isBoolean())) {
144+
boolean expectedValue = document.getBoolean(key).getValue();
145+
assertNotNull(actualMechanismProperty);
146+
assertEquals(expectedValue, actualMechanismProperty);
147+
} else {
148+
fail("unsupported property type");
153149
}
154150
}
155151
}

0 commit comments

Comments
 (0)