Skip to content

Commit cc47045

Browse files
authored
Improving Unit Test Coverage (#100)
* Prototyping Firestore integration for Java * Some code cleanup * Updating comments * Code cleanup * Removed getInstance() methods from FirestoreClient and added getFirestore() methods. * Minor cleanup * Adding Firestore OAuth scopes * Some documentation updates * Reverted a doc change * Updating GCS dependency version (#89) * Netty-based websocket impl * Refactored the Netty stuff to a separate util class * More code clean up and removing tubesock package * Using the SDK ThreadManager for DB websocket threads * More code cleanup and error checks * Handling connection drop events * Handling connection loss events * Adding documentation * Removed string list reader * Removing redundant whitespace * Revert "Using the SDK ThreadManager for DB websocket threads" This reverts commit 8e90610. * src/main/java/com/google/firebase/database/connection/util/StringListReader.java * Added StringListReader back * Re-updated websocket client * reverting more syntactic changes * Adding new line * Added documentation; Using a more secure trust manager; Other cleanup * Removed unused import * Using the port on URI when available * Added jacoco plugin and parser * Coverage reporter impl * More unit tests and cleaning up dead code * More tests for RTDB * More database tests * Some unit tests for Repo * More tests for Repo * Cleaning up mocks * debug info * More debug info * Updated repo test * Cleaned up test code * Removed some code changes * Connection tests * More unit tests * Updated test * More unit tests for PersistentConnectionImpl * Refactored persistent conn tests * More connection tests * Some user management and DB Node tests * StorageClient unit tests * cleaned up PersistentConnectionTest * Fixed typo * Removing websocket commpression handler * Unit tests for Connection class * More tests for the connection package * Unit tests for GaeExecutorService * Updated test * Fixing a lint error * Added more tests * More test coverage * Refactored GaeExecutorService class * Refactored various connection factory interfaces * Minor refactoring * Refactoring iterative test case with a map
1 parent 32b3143 commit cc47045

22 files changed

+1602
-224
lines changed

src/main/java/com/google/firebase/cloud/StorageClient.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.google.cloud.storage.Bucket;
2323
import com.google.cloud.storage.Storage;
2424
import com.google.cloud.storage.StorageOptions;
25+
import com.google.common.annotations.VisibleForTesting;
2526
import com.google.common.base.Strings;
2627
import com.google.firebase.FirebaseApp;
2728
import com.google.firebase.ImplFirebaseTrampolines;
@@ -41,12 +42,10 @@ public class StorageClient {
4142
private final FirebaseApp app;
4243
private final Storage storage;
4344

44-
private StorageClient(FirebaseApp app) {
45+
@VisibleForTesting
46+
StorageClient(FirebaseApp app, Storage storage) {
4547
this.app = checkNotNull(app, "FirebaseApp must not be null");
46-
this.storage = StorageOptions.newBuilder()
47-
.setCredentials(ImplFirebaseTrampolines.getCredentials(app))
48-
.build()
49-
.getService();
48+
this.storage = checkNotNull(storage, "Storage must not be null");
5049
}
5150

5251
public static StorageClient getInstance() {
@@ -57,7 +56,12 @@ public static synchronized StorageClient getInstance(FirebaseApp app) {
5756
StorageClientService service = ImplFirebaseTrampolines.getService(app, SERVICE_ID,
5857
StorageClientService.class);
5958
if (service == null) {
60-
service = ImplFirebaseTrampolines.addService(app, new StorageClientService(app));
59+
Storage storage = StorageOptions.newBuilder()
60+
.setCredentials(ImplFirebaseTrampolines.getCredentials(app))
61+
.build()
62+
.getService();
63+
StorageClient client = new StorageClient(app, storage);
64+
service = ImplFirebaseTrampolines.addService(app, new StorageClientService(client));
6165
}
6266
return service.getInstance();
6367
}
@@ -99,8 +103,8 @@ public Bucket bucket(String name) {
99103

100104
private static class StorageClientService extends FirebaseService<StorageClient> {
101105

102-
StorageClientService(FirebaseApp app) {
103-
super(SERVICE_ID, new StorageClient(app));
106+
StorageClientService(StorageClient client) {
107+
super(SERVICE_ID, client);
104108
}
105109

106110
@Override

src/main/java/com/google/firebase/database/connection/Connection.java

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.google.firebase.database.connection;
1818

19+
import com.google.common.annotations.VisibleForTesting;
1920
import com.google.firebase.database.logging.LogWrapper;
2021

2122
import java.util.HashMap;
@@ -39,24 +40,36 @@ class Connection implements WebsocketConnection.Delegate {
3940
private static final String SERVER_HELLO_HOST = "h";
4041
private static final String SERVER_HELLO_SESSION_ID = "s";
4142
private static long connectionIds = 0;
43+
4244
private final LogWrapper logger;
43-
private HostInfo hostInfo;
45+
private final HostInfo hostInfo;
46+
private final Delegate delegate;
47+
4448
private WebsocketConnection conn;
45-
private Delegate delegate;
4649
private State state;
4750

48-
public Connection(
51+
Connection(
4952
ConnectionContext context,
5053
HostInfo hostInfo,
5154
String cachedHost,
5255
Delegate delegate,
5356
String optLastSessionId) {
57+
this(context, hostInfo, delegate,
58+
new DefaultWebsocketConnectionFactory(context, hostInfo, cachedHost, optLastSessionId));
59+
}
60+
61+
@VisibleForTesting
62+
Connection(
63+
ConnectionContext context,
64+
HostInfo hostInfo,
65+
Delegate delegate,
66+
WebsocketConnectionFactory connFactory) {
5467
long connId = connectionIds++;
5568
this.hostInfo = hostInfo;
5669
this.delegate = delegate;
5770
this.logger = new LogWrapper(context.getLogger(), Connection.class, "conn_" + connId);
5871
this.state = State.REALTIME_CONNECTING;
59-
this.conn = new WebsocketConnection(context, hostInfo, cachedHost, this, optLastSessionId);
72+
this.conn = connFactory.newConnection(this);
6073
}
6174

6275
public void open() {
@@ -246,11 +259,6 @@ private void sendData(Map<String, Object> data, boolean isSensitive) {
246259
}
247260
}
248261

249-
// For testing
250-
public void injectConnectionFailure() {
251-
this.close();
252-
}
253-
254262
public enum DisconnectReason {
255263
SERVER_RESET,
256264
OTHER
@@ -262,6 +270,34 @@ private enum State {
262270
REALTIME_DISCONNECTED
263271
}
264272

273+
interface WebsocketConnectionFactory {
274+
WebsocketConnection newConnection(WebsocketConnection.Delegate delegate);
275+
}
276+
277+
private static class DefaultWebsocketConnectionFactory implements WebsocketConnectionFactory {
278+
279+
final ConnectionContext context;
280+
final HostInfo hostInfo;
281+
final String cachedHost;
282+
final String optLastSessionId;
283+
284+
DefaultWebsocketConnectionFactory(
285+
ConnectionContext context,
286+
HostInfo hostInfo,
287+
String cachedHost,
288+
String optLastSessionId) {
289+
this.context = context;
290+
this.hostInfo = hostInfo;
291+
this.cachedHost = cachedHost;
292+
this.optLastSessionId = optLastSessionId;
293+
}
294+
295+
@Override
296+
public WebsocketConnection newConnection(WebsocketConnection.Delegate delegate) {
297+
return new WebsocketConnection(context, hostInfo, cachedHost, delegate, optLastSessionId);
298+
}
299+
}
300+
265301
public interface Delegate {
266302

267303
void onCacheHost(String host);

src/main/java/com/google/firebase/database/connection/PersistentConnectionImpl.java

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020

2121
import com.google.firebase.database.connection.util.RetryHelper;
2222
import com.google.firebase.database.logging.LogWrapper;
23-
import com.google.firebase.database.util.AndroidSupport;
2423
import com.google.firebase.database.util.GAuthToken;
2524

2625
import java.util.ArrayList;
@@ -93,13 +92,16 @@ public class PersistentConnectionImpl implements Connection.Delegate, Persistent
9392
private static final String IDLE_INTERRUPT_REASON = "connection_idle";
9493
private static final String TOKEN_REFRESH_INTERRUPT_REASON = "token_refresh";
9594
private static long connectionIds = 0;
95+
9696
private final Delegate delegate;
9797
private final HostInfo hostInfo;
9898
private final ConnectionContext context;
99+
private final ConnectionFactory connFactory;
99100
private final ConnectionAuthTokenProvider authTokenProvider;
100101
private final ScheduledExecutorService executorService;
101102
private final LogWrapper logger;
102103
private final RetryHelper retryHelper;
104+
103105
private String cachedHost;
104106
private HashSet<String> interruptReasons = new HashSet<>();
105107
private boolean firstConnection = true;
@@ -123,13 +125,19 @@ public class PersistentConnectionImpl implements Connection.Delegate, Persistent
123125
private long lastWriteTimestamp;
124126
private boolean hasOnDisconnects;
125127

126-
public PersistentConnectionImpl(
127-
ConnectionContext context, HostInfo info, final Delegate delegate) {
128-
this.delegate = delegate;
128+
public PersistentConnectionImpl(ConnectionContext context, HostInfo info, Delegate delegate) {
129+
this(context, info, delegate, new DefaultConnectionFactory());
130+
}
131+
132+
PersistentConnectionImpl(
133+
ConnectionContext context, HostInfo info, Delegate delegate, ConnectionFactory connFactory) {
134+
129135
this.context = context;
136+
this.hostInfo = info;
137+
this.delegate = delegate;
138+
this.connFactory = connFactory;
130139
this.executorService = context.getExecutorService();
131140
this.authTokenProvider = context.getAuthTokenProvider();
132-
this.hostInfo = info;
133141
this.listens = new HashMap<>();
134142
this.requestCBHash = new HashMap<>();
135143
this.outstandingPuts = new HashMap<>();
@@ -422,7 +430,7 @@ public boolean isInterrupted(String reason) {
422430
return interruptReasons.contains(reason);
423431
}
424432

425-
boolean shouldReconnect() {
433+
private boolean shouldReconnect() {
426434
return interruptReasons.size() == 0;
427435
}
428436

@@ -524,20 +532,19 @@ public void onError(String error) {
524532
}
525533
}
526534

527-
public void openNetworkConnection(String token) {
535+
private void openNetworkConnection(String token) {
528536
hardAssert(
529-
this.connectionState == ConnectionState.GettingToken,
537+
connectionState == ConnectionState.GettingToken,
530538
"Trying to open network connection while in the wrong state: %s",
531-
this.connectionState);
539+
connectionState);
532540
// User might have logged out. Positive auth status is handled after authenticating with
533541
// the server
534542
if (token == null) {
535-
this.delegate.onAuthStatus(false);
543+
delegate.onAuthStatus(false);
536544
}
537-
this.authToken = token;
538-
this.connectionState = ConnectionState.Connecting;
539-
realtime =
540-
new Connection(this.context, this.hostInfo, this.cachedHost, this, this.lastSessionId);
545+
authToken = token;
546+
connectionState = ConnectionState.Connecting;
547+
realtime = connFactory.newConnection(this);
541548
realtime.open();
542549
}
543550

@@ -1054,17 +1061,9 @@ private void warnOnListenerWarnings(List<String> warnings, ListenQuerySpec query
10541061

10551062
private void sendConnectStats() {
10561063
Map<String, Integer> stats = new HashMap<>();
1057-
if (AndroidSupport.isAndroid()) {
1058-
if (this.context.isPersistenceEnabled()) {
1059-
stats.put("persistence.android.enabled", 1);
1060-
}
1061-
stats.put("sdk.android." + context.getClientSdkVersion().replace('.', '-'), 1);
1062-
// TODO: Also send stats for connection version
1063-
} else {
1064-
assert !this.context.isPersistenceEnabled()
1065-
: "Stats for persistence on JVM missing (persistence not yet supported)";
1066-
stats.put("sdk.admin_java." + context.getClientSdkVersion().replace('.', '-'), 1);
1067-
}
1064+
assert !this.context.isPersistenceEnabled()
1065+
: "Stats for persistence on JVM missing (persistence not yet supported)";
1066+
stats.put("sdk.admin_java." + context.getClientSdkVersion().replace('.', '-'), 1);
10681067
if (logger.logsDebug()) {
10691068
logger.debug("Sending first connection stats");
10701069
}
@@ -1137,13 +1136,6 @@ private boolean idleHasTimedOut() {
11371136
return isIdle() && now > (this.lastWriteTimestamp + IDLE_TIMEOUT);
11381137
}
11391138

1140-
// For testing
1141-
public void injectConnectionFailure() {
1142-
if (this.realtime != null) {
1143-
this.realtime.injectConnectionFailure();
1144-
}
1145-
}
1146-
11471139
private enum ConnectionState {
11481140
Disconnected,
11491141
GettingToken,
@@ -1215,15 +1207,15 @@ private OutstandingListen(
12151207
this.tag = tag;
12161208
}
12171209

1218-
public ListenQuerySpec getQuery() {
1210+
ListenQuerySpec getQuery() {
12191211
return query;
12201212
}
12211213

1222-
public Long getTag() {
1214+
Long getTag() {
12231215
return this.tag;
12241216
}
12251217

1226-
public ListenHashProvider getHashFunction() {
1218+
ListenHashProvider getHashFunction() {
12271219
return this.hashFunction;
12281220
}
12291221

@@ -1247,23 +1239,23 @@ private OutstandingPut(
12471239
this.onComplete = onComplete;
12481240
}
12491241

1250-
public String getAction() {
1242+
String getAction() {
12511243
return action;
12521244
}
12531245

1254-
public Map<String, Object> getRequest() {
1246+
Map<String, Object> getRequest() {
12551247
return request;
12561248
}
12571249

1258-
public RequestResultCallback getOnComplete() {
1250+
RequestResultCallback getOnComplete() {
12591251
return onComplete;
12601252
}
12611253

1262-
public void markSent() {
1254+
void markSent() {
12631255
this.sent = true;
12641256
}
12651257

1266-
public boolean wasSent() {
1258+
boolean wasSent() {
12671259
return this.sent;
12681260
}
12691261
}
@@ -1299,4 +1291,18 @@ public RequestResultCallback getOnComplete() {
12991291
return onComplete;
13001292
}
13011293
}
1294+
1295+
interface ConnectionFactory {
1296+
Connection newConnection(PersistentConnectionImpl delegate);
1297+
}
1298+
1299+
private static class DefaultConnectionFactory implements ConnectionFactory {
1300+
@Override
1301+
public Connection newConnection(PersistentConnectionImpl delegate) {
1302+
return new Connection(delegate.context, delegate.hostInfo, delegate.cachedHost,
1303+
delegate, delegate.lastSessionId);
1304+
}
1305+
}
1306+
1307+
13021308
}

0 commit comments

Comments
 (0)