Skip to content

Commit dd0ba1e

Browse files
committed
Added unit tests for the new functionality
1 parent a74ccc1 commit dd0ba1e

File tree

6 files changed

+565
-21
lines changed

6 files changed

+565
-21
lines changed

src/main/java/com/google/firebase/internal/BaseHttpErrorHandler.java renamed to src/main/java/com/google/firebase/internal/AbstractHttpErrorHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
/**
3232
* An abstract HttpErrorHandler implementation that maps HTTP status codes to Firebase error codes.
3333
*/
34-
public abstract class BaseHttpErrorHandler<T extends FirebaseException>
34+
public abstract class AbstractHttpErrorHandler<T extends FirebaseException>
3535
implements HttpErrorHandler<T> {
3636

3737
private static final Map<Integer, ErrorCode> HTTP_ERROR_CODES =

src/main/java/com/google/firebase/internal/PlatformErrorHandler.java renamed to src/main/java/com/google/firebase/internal/AbstractPlatformErrorHandler.java

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,15 @@
2828
import java.io.IOException;
2929

3030
/**
31-
* An abstract HttpErrorHandler that handles Google Cloud error responses.
31+
* An abstract HttpErrorHandler that handles Google Cloud error responses. Format of these
32+
* error responses are defined at https://cloud.google.com/apis/design/errors.
3233
*/
33-
public abstract class PlatformErrorHandler<T extends FirebaseException>
34-
extends BaseHttpErrorHandler<T> {
34+
public abstract class AbstractPlatformErrorHandler<T extends FirebaseException>
35+
extends AbstractHttpErrorHandler<T> {
3536

3637
protected final JsonFactory jsonFactory;
3738

38-
public PlatformErrorHandler(JsonFactory jsonFactory) {
39+
public AbstractPlatformErrorHandler(JsonFactory jsonFactory) {
3940
this.jsonFactory = checkNotNull(jsonFactory, "jsonFactory must not be null");
4041
}
4142

@@ -61,17 +62,16 @@ protected final ErrorParams getErrorParams(
6162

6263
private PlatformErrorResponse parseErrorResponse(String content) {
6364
PlatformErrorResponse response = new PlatformErrorResponse();
64-
if (content == null) {
65-
return response;
65+
if (!Strings.isNullOrEmpty(content)) {
66+
try {
67+
jsonFactory.createJsonParser(content).parseAndClose(response);
68+
} catch (IOException e) {
69+
// Ignore any error that may occur while parsing the error response. The server
70+
// may have responded with a non-json payload. Return an empty return value, and
71+
// let the base class logic come into play.
72+
}
6673
}
6774

68-
try {
69-
jsonFactory.createJsonParser(content).parseAndClose(response);
70-
} catch (IOException e) {
71-
// Ignore any error that may occur while parsing the error response. The server
72-
// may have responded with a non-json payload. Return an empty return value, and
73-
// let the base class logic come into play.
74-
}
7575
return response;
7676
}
7777

src/main/java/com/google/firebase/internal/ErrorHandlingHttpClient.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,10 @@ public ErrorHandlingHttpClient(
5050
errorHandler);
5151
}
5252

53-
public ErrorHandlingHttpClient(HttpRequestFactory requestFactory,
54-
JsonFactory jsonFactory, HttpErrorHandler<T> errorHandler) {
53+
public ErrorHandlingHttpClient(
54+
HttpRequestFactory requestFactory,
55+
JsonFactory jsonFactory,
56+
HttpErrorHandler<T> errorHandler) {
5557
this.requestFactory = checkNotNull(requestFactory, "requestFactory must not be null");
5658
this.jsonFactory = checkNotNull(jsonFactory, "jsonFactory must not be null");
5759
this.errorHandler = checkNotNull(errorHandler, "errorHandler must not be null");

src/main/java/com/google/firebase/internal/HttpRequestInfo.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,19 @@
1616

1717
package com.google.firebase.internal;
1818

19-
import static com.google.common.base.Preconditions.checkArgument;
20-
2119
import com.google.api.client.http.GenericUrl;
2220
import com.google.api.client.http.HttpContent;
2321
import com.google.api.client.http.HttpMethods;
2422
import com.google.api.client.http.HttpRequest;
2523
import com.google.api.client.http.HttpRequestFactory;
2624
import com.google.api.client.http.HttpResponseInterceptor;
27-
import com.google.common.base.Strings;
2825
import java.io.IOException;
2926
import java.util.HashMap;
3027
import java.util.Map;
3128

3229
/**
33-
* Internal API for configuring outgoing HTTP requests.
30+
* Internal API for configuring outgoing HTTP requests. To be used with the
31+
* {@link ErrorHandlingHttpClient} class.
3432
*/
3533
public final class HttpRequestInfo {
3634

@@ -41,7 +39,6 @@ public final class HttpRequestInfo {
4139
private HttpResponseInterceptor interceptor;
4240

4341
private HttpRequestInfo(String method, String url, HttpContent content) {
44-
checkArgument(!Strings.isNullOrEmpty(method), "method must not be null or empty");
4542
this.method = method;
4643
this.url = new GenericUrl(url);
4744
this.content = content;
Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
/*
2+
* Copyright 2020 Google 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 com.google.firebase.internal;
18+
19+
import static org.junit.Assert.assertEquals;
20+
import static org.junit.Assert.assertNotNull;
21+
import static org.junit.Assert.assertNull;
22+
import static org.junit.Assert.assertSame;
23+
import static org.junit.Assert.fail;
24+
25+
import com.google.api.client.googleapis.util.Utils;
26+
import com.google.api.client.http.HttpStatusCodes;
27+
import com.google.api.client.http.LowLevelHttpRequest;
28+
import com.google.api.client.testing.http.MockHttpTransport;
29+
import com.google.api.client.testing.http.MockLowLevelHttpResponse;
30+
import com.google.api.client.util.GenericData;
31+
import com.google.firebase.ErrorCode;
32+
import com.google.firebase.FirebaseException;
33+
import com.google.firebase.IncomingHttpResponse;
34+
import java.io.IOException;
35+
import org.junit.Test;
36+
37+
public class AbstractPlatformErrorHandlerTest {
38+
39+
private static final HttpRequestInfo TEST_REQUEST = HttpRequestInfo.buildGetRequest(
40+
"https://firebase.google.com");
41+
42+
@Test
43+
public void testPlatformError() {
44+
String payload = "{\"error\": {\"status\": \"UNAVAILABLE\", \"message\": \"Test error\"}}";
45+
MockLowLevelHttpResponse response = new MockLowLevelHttpResponse()
46+
.setStatusCode(HttpStatusCodes.STATUS_CODE_SERVER_ERROR)
47+
.setContent(payload);
48+
ErrorHandlingHttpClient<FirebaseException> client = createHttpClient(response);
49+
50+
try {
51+
client.sendAndParse(TEST_REQUEST, GenericData.class);
52+
fail("No exception thrown for HTTP error response");
53+
} catch (FirebaseException e) {
54+
// TODO: Uncomment this line when getErrorCode is public
55+
// assertEquals(ErrorCode.UNAVAILABLE, e.getErrorCode());
56+
assertEquals("Test error", e.getMessage());
57+
assertHttpResponse(e, HttpStatusCodes.STATUS_CODE_SERVER_ERROR, payload);
58+
assertNotNull(e.getCause());
59+
}
60+
}
61+
62+
@Test
63+
public void testNonJsonError() {
64+
String payload = "not json";
65+
MockLowLevelHttpResponse response = new MockLowLevelHttpResponse()
66+
.setStatusCode(HttpStatusCodes.STATUS_CODE_SERVER_ERROR)
67+
.setContent(payload);
68+
ErrorHandlingHttpClient<FirebaseException> client = createHttpClient(response);
69+
70+
try {
71+
client.sendAndParse(TEST_REQUEST, GenericData.class);
72+
fail("No exception thrown for HTTP error response");
73+
} catch (FirebaseException e) {
74+
// TODO: Uncomment this line when getErrorCode is public
75+
// assertEquals(ErrorCode.INTERNAL, e.getErrorCode());
76+
assertEquals("Unexpected HTTP response with status: 500\nnot json", e.getMessage());
77+
assertHttpResponse(e, HttpStatusCodes.STATUS_CODE_SERVER_ERROR, payload);
78+
assertNotNull(e.getCause());
79+
}
80+
}
81+
82+
@Test
83+
public void testPlatformErrorWithoutCode() {
84+
String payload = "{\"error\": {\"message\": \"Test error\"}}";
85+
MockLowLevelHttpResponse response = new MockLowLevelHttpResponse()
86+
.setStatusCode(HttpStatusCodes.STATUS_CODE_SERVER_ERROR)
87+
.setContent(payload);
88+
ErrorHandlingHttpClient<FirebaseException> client = createHttpClient(response);
89+
90+
try {
91+
client.sendAndParse(TEST_REQUEST, GenericData.class);
92+
fail("No exception thrown for HTTP error response");
93+
} catch (FirebaseException e) {
94+
// TODO: Uncomment this line when getErrorCode is public
95+
// assertEquals(ErrorCode.INTERNAL, e.getErrorCode());
96+
assertEquals("Test error", e.getMessage());
97+
assertHttpResponse(e, HttpStatusCodes.STATUS_CODE_SERVER_ERROR, payload);
98+
assertNotNull(e.getCause());
99+
}
100+
}
101+
102+
@Test
103+
public void testPlatformErrorWithoutMessage() {
104+
String payload = "{\"error\": {\"status\": \"INVALID_ARGUMENT\"}}";
105+
MockLowLevelHttpResponse response = new MockLowLevelHttpResponse()
106+
.setStatusCode(HttpStatusCodes.STATUS_CODE_SERVER_ERROR)
107+
.setContent(payload);
108+
ErrorHandlingHttpClient<FirebaseException> client = createHttpClient(response);
109+
110+
try {
111+
client.sendAndParse(TEST_REQUEST, GenericData.class);
112+
fail("No exception thrown for HTTP error response");
113+
} catch (FirebaseException e) {
114+
// TODO: Uncomment this line when getErrorCode is public
115+
// assertEquals(ErrorCode.INVALID_ARGUMENT, e.getErrorCode());
116+
assertEquals("Unexpected HTTP response with status: 500\n" + payload, e.getMessage());
117+
assertHttpResponse(e, HttpStatusCodes.STATUS_CODE_SERVER_ERROR, payload);
118+
assertNotNull(e.getCause());
119+
}
120+
}
121+
122+
@Test
123+
public void testPlatformErrorWithoutCodeOrMessage() {
124+
String payload = "{}";
125+
MockLowLevelHttpResponse response = new MockLowLevelHttpResponse()
126+
.setStatusCode(HttpStatusCodes.STATUS_CODE_SERVER_ERROR)
127+
.setContent(payload);
128+
ErrorHandlingHttpClient<FirebaseException> client = createHttpClient(response);
129+
130+
try {
131+
client.sendAndParse(TEST_REQUEST, GenericData.class);
132+
fail("No exception thrown for HTTP error response");
133+
} catch (FirebaseException e) {
134+
// TODO: Uncomment this line when getErrorCode is public
135+
// assertEquals(ErrorCode.INTERNAL, e.getErrorCode());
136+
assertEquals("Unexpected HTTP response with status: 500\n" + payload, e.getMessage());
137+
assertHttpResponse(e, HttpStatusCodes.STATUS_CODE_SERVER_ERROR, payload);
138+
assertNotNull(e.getCause());
139+
}
140+
}
141+
142+
@Test
143+
public void testNetworkError() {
144+
final IOException exception = new IOException("Test");
145+
MockHttpTransport transport = new MockHttpTransport(){
146+
@Override
147+
public LowLevelHttpRequest buildRequest(String method, String url) throws IOException {
148+
throw exception;
149+
}
150+
};
151+
ErrorHandlingHttpClient<FirebaseException> client = new ErrorHandlingHttpClient<>(
152+
transport.createRequestFactory(),
153+
Utils.getDefaultJsonFactory(),
154+
new TestPlatformErrorHandler());
155+
156+
try {
157+
client.sendAndParse(TEST_REQUEST, GenericData.class);
158+
fail("No exception thrown for HTTP error response");
159+
} catch (FirebaseException e) {
160+
// TODO: Uncomment this line when getErrorCode is public
161+
// assertEquals(ErrorCode.UNKNOWN, e.getErrorCode());
162+
assertEquals("IO error", e.getMessage());
163+
assertNull(e.getHttpResponse());
164+
assertSame(exception, e.getCause());
165+
}
166+
}
167+
168+
@Test
169+
public void testParseError() {
170+
String payload = "not json";
171+
MockLowLevelHttpResponse response = new MockLowLevelHttpResponse()
172+
.setContent(payload);
173+
ErrorHandlingHttpClient<FirebaseException> client = createHttpClient(response);
174+
175+
try {
176+
client.sendAndParse(TEST_REQUEST, GenericData.class);
177+
fail("No exception thrown for HTTP error response");
178+
} catch (FirebaseException e) {
179+
// TODO: Uncomment this line when getErrorCode is public
180+
// assertEquals(ErrorCode.UNKNOWN, e.getErrorCode());
181+
assertEquals("Parse error", e.getMessage());
182+
assertHttpResponse(e, HttpStatusCodes.STATUS_CODE_OK, payload);
183+
assertNotNull(e.getCause());
184+
}
185+
}
186+
187+
@Test
188+
public void testUnknownHttpError() {
189+
String payload = "{\"error\": {\"message\": \"Test error\"}}";
190+
MockLowLevelHttpResponse response = new MockLowLevelHttpResponse()
191+
.setStatusCode(512)
192+
.setContent(payload);
193+
ErrorHandlingHttpClient<FirebaseException> client = createHttpClient(response);
194+
195+
try {
196+
client.sendAndParse(TEST_REQUEST, GenericData.class);
197+
fail("No exception thrown for HTTP error response");
198+
} catch (FirebaseException e) {
199+
// TODO: Uncomment this line when getErrorCode is public
200+
// assertEquals(ErrorCode.UNKNOWN, e.getErrorCode());
201+
assertEquals("Test error", e.getMessage());
202+
assertHttpResponse(e, 512, payload);
203+
assertNotNull(e.getCause());
204+
}
205+
}
206+
207+
private ErrorHandlingHttpClient<FirebaseException> createHttpClient(
208+
MockLowLevelHttpResponse response) {
209+
MockHttpTransport transport = new MockHttpTransport.Builder()
210+
.setLowLevelHttpResponse(response)
211+
.build();
212+
return new ErrorHandlingHttpClient<>(
213+
transport.createRequestFactory(),
214+
Utils.getDefaultJsonFactory(),
215+
new TestPlatformErrorHandler());
216+
}
217+
218+
private void assertHttpResponse(FirebaseException e, int statusCode, String content) {
219+
IncomingHttpResponse httpResponse = e.getHttpResponse();
220+
assertNotNull(httpResponse);
221+
assertEquals(statusCode, httpResponse.getStatusCode());
222+
assertEquals(content, httpResponse.getContent());
223+
assertEquals("GET", httpResponse.getRequest().getMethod());
224+
}
225+
226+
private static class TestPlatformErrorHandler extends
227+
AbstractPlatformErrorHandler<FirebaseException> {
228+
229+
TestPlatformErrorHandler() {
230+
super(Utils.getDefaultJsonFactory());
231+
}
232+
233+
@Override
234+
protected FirebaseException createException(ErrorParams params) {
235+
return new FirebaseException(params.getErrorCode(), params.getMessage(),
236+
params.getResponse(), params.getException());
237+
}
238+
239+
@Override
240+
public FirebaseException handleIOException(IOException e) {
241+
return new FirebaseException(ErrorCode.UNKNOWN, "IO error", null, e);
242+
}
243+
244+
@Override
245+
public FirebaseException handleParseException(IOException e, IncomingHttpResponse response) {
246+
return new FirebaseException(ErrorCode.UNKNOWN, "Parse error", response, e);
247+
}
248+
}
249+
}

0 commit comments

Comments
 (0)