X-Git-Url: https://juplo.de/gitweb/?p=facebook-utils;a=blobdiff_plain;f=src%2Ftest%2Fjava%2Fde%2Fjuplo%2Ffacebook%2Ferrors%2FGraphApiErrorHandlerTest.java;fp=src%2Ftest%2Fjava%2Fde%2Fjuplo%2Ffacebook%2Ferrors%2FGraphApiErrorHandlerTest.java;h=9fc7fc35d0bafa0431a94f06c659cfb5e24f7ae0;hp=0000000000000000000000000000000000000000;hb=89065da8bbd59c4973d837c10cf63d967f6357cc;hpb=aa08a5cc575e5228c267686ba668cdbb3f361a90 diff --git a/src/test/java/de/juplo/facebook/errors/GraphApiErrorHandlerTest.java b/src/test/java/de/juplo/facebook/errors/GraphApiErrorHandlerTest.java new file mode 100644 index 0000000..9fc7fc3 --- /dev/null +++ b/src/test/java/de/juplo/facebook/errors/GraphApiErrorHandlerTest.java @@ -0,0 +1,802 @@ +package de.juplo.facebook.errors; + + +import de.juplo.facebook.errors.GraphApiException.Type; +import java.util.Date; +import java.util.Map; +import java.util.Set; +import javax.annotation.Resource; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.client.http.OAuth2ErrorHandler; +import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; +import org.springframework.security.oauth2.client.resource.UserApprovalRequiredException; +import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException; +import org.springframework.security.oauth2.client.token.AccessTokenProvider; +import org.springframework.security.oauth2.client.token.AccessTokenRequest; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import static org.springframework.security.oauth2.common.OAuth2AccessToken.OAUTH2_TYPE; +import org.springframework.security.oauth2.common.OAuth2RefreshToken; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.web.client.HttpClientErrorException; + + + +/** + * + * @author Kai Moritz + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration( + locations = { + "classpath:/spring/test-facebook-error-handler.xml" + }) +public class GraphApiErrorHandlerTest +{ + private static final Logger log = + LoggerFactory.getLogger(GraphApiErrorHandlerTest.class); + + @Resource + private OAuth2RestTemplate clientTemplate; + + private MockClientHttpRequestFactory requestFactory; + + + @Test + public void testError1() + { + log.info("testError1"); + + + requestFactory.setBody( + "{\n" + + " \"error\":\n" + + " {\n" + + " \"message\": \"An unknown error has occurred.\",\n" + + " \"type\": \"OAuthException\",\n" + + " \"code\": 1\n" + + " }\n" + + "}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(UnknownErrorException e) + { + log.debug("{}", e.toString()); + assertEquals("invalid_request", e.getOAuth2ErrorCode()); + assertEquals(new Integer(1), e.getCode()); + assertEquals("An unknown error has occurred.", e.getMessage()); + assertEquals(Type.OAuthException, e.getType()); + } + } + + @Test + public void testError2() + { + log.info("testError2"); + + + requestFactory.setBody( + "{\n" + + " \"error\":\n" + + " {\n" + + " \"message\": \"An unexpected error has occurred. Please retry your request later.\",\n" + + " \"type\": \"OAuthException\",\n" + + " \"code\": 2\n" + + " }\n" + + "}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(UnexpectedErrorException e) + { + log.debug("{}", e.toString()); + assertEquals("invalid_request", e.getOAuth2ErrorCode()); + assertEquals(new Integer(2), e.getCode()); + assertEquals("An unexpected error has occurred. Please retry your request later.", e.getMessage()); + assertEquals(Type.OAuthException, e.getType()); + } + } + + @Test + public void testError21() + { + log.info("testError21"); + + + requestFactory.setBody( + "{\n" + + " \"error\":\n" + + " {\n" + + " \"message\": \"(#21) Page ID 590408587650316 was migrated to page ID 1421620791415603. Please update your API calls to the new ID\",\n" + + " \"type\": \"OAuthException\",\n" + + " \"code\": 21\n" + + " }\n" + + "}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(PageMigratedException e) + { + log.debug("{}", e.toString()); + assertEquals("invalid_request", e.getOAuth2ErrorCode()); + assertEquals(new Integer(21), e.getCode()); + assertEquals("(#21) Page ID 590408587650316 was migrated to page ID 1421620791415603. Please update your API calls to the new ID", e.getMessage()); + assertEquals(Type.OAuthException, e.getType()); + } + } + + @Test + public void testError100() + { + log.info("testError100"); + + + requestFactory.setBody( + "{\n" + + " \"error\":\n" + + " {\n" + + " \"message\": \"Unsupported get request.\",\n" + + " \"type\": \"GraphMethodException\",\n" + + " \"code\": 100\n" + + " }\n" + + "}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(UnsupportedGetRequestException e) + { + log.debug("{}", e.toString()); + assertEquals("invalid_request", e.getOAuth2ErrorCode()); + assertEquals(new Integer(100), e.getCode()); + assertEquals("Unsupported get request.", e.getMessage()); + assertEquals(Type.GraphMethodException, e.getType()); + } + } + + @Test + public void testError104() + { + log.info("testError104"); + + requestFactory.setBody("{\"error\":{\"message\":\"An access token is required to request this resource.\",\"type\":\"OAuthException\",\"code\":104,\"fbtrace_id\":\"E2Jjkj5++LL\"}}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(AccessTokenRequiredException e) + { + log.debug("{}", e.toString()); + assertEquals("invalid_request", e.getOAuth2ErrorCode()); + assertEquals(new Integer(104), e.getCode()); + assertEquals("An access token is required to request this resource.", e.getMessage()); + assertEquals(Type.OAuthException, e.getType()); + assertEquals("E2Jjkj5++LL", e.getTraceId()); + } + } + + @Test + public void testError613() + { + log.info("testError613"); + + + requestFactory.setBody( + "{\n" + + " \"error\":\n" + + " {\n" + + " \"message\": \"(#613) Calls to stream have exceeded the rate of 600 calls per 600 seconds.\",\n" + + " \"type\": \"OAuthException\",\n" + + " \"code\": 613\n" + + " }\n" + + "}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(RateExceededException e) + { + log.debug("{}", e.toString()); + assertEquals("invalid_request", e.getOAuth2ErrorCode()); + assertEquals(new Integer(613), e.getCode()); + assertEquals("(#613) Calls to stream have exceeded the rate of 600 calls per 600 seconds.", e.getMessage()); + assertEquals(Type.OAuthException, e.getType()); + } + } + + @Test + public void testError2200() + { + requestFactory.setBody("{\"error\":{\"message\":\"(#2200) callback verification failed: \",\"type\":\"OAuthException\",\"code\":2200,\"fbtrace_id\":\"ESLjoZKvPXg\"}}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(CallbackVerificationFailedException e) + { + log.debug("{}", e.toString()); + assertEquals("invalid_request", e.getOAuth2ErrorCode()); + assertEquals(new Integer(2200), e.getCode()); + assertEquals("(#2200) callback verification failed: ", e.getMessage()); + assertEquals(Type.OAuthException, e.getType()); + assertEquals("ESLjoZKvPXg", e.getTraceId()); + } + } + + @Test + public void testUnmappedError() + { + log.info("testUnmappedError"); + + + requestFactory.setBody( + "{\n" + + " \"error\":\n" + + " {\n" + + " \"message\": \"This error does not exist.\",\n" + + " \"type\": \"NonexistentTypeException\",\n" + + " \"code\": 999999999\n" + + " }\n" + + "}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(GraphApiException e) + { + log.debug("{}", e.toString()); + assertEquals("invalid_request", e.getOAuth2ErrorCode()); + assertEquals(new Integer(999999999), e.getCode()); + assertEquals("This error does not exist.", e.getMessage()); + try + { + Type type = e.getType(); + log.error("unknown type: {}", type); + fail("unmapped type was resolved by enum: " + type); + } + catch (IllegalArgumentException ee) {} + } + } + + @Test + public void testUnmappedErrors() + { + log.info("testUnmappedErrors"); + + + requestFactory.setBody( + "{\n" + + " \"error\":\n" + + " {\n" + + " \"message\": null,\n" + + " \"type\": \"WhateverTypeException\",\n" + + " \"code\": 999999999\n" + + " }\n" + + "}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(UnmappedErrorException e) + { + log.debug("{}", e.toString()); + assertNull(e.getMessage()); + try + { + Type type = e.getType(); + log.error("unknown type: {}", type); + fail("unmapped type was resolved by enum: " + type); + } + catch (IllegalArgumentException ee) {} + assertEquals(new Integer(999999999), e.getCode()); + assertNull(e.getSubCode()); + assertNull(e.getUserTitle()); + assertNull(e.getUserMessage()); + assertNull(e.getTraceId()); + } + catch(Exception e) + { + fail("A wrong exception was thrown: " + e.toString()); + } + + + requestFactory.setBody( + "{\n" + + " \"error\":\n" + + " {\n" + + " \"type\": \"WhateverTypeException\",\n" + + " \"code\": 999999999\n" + + " }\n" + + "}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(UnmappedErrorException e) + { + log.debug("{}", e.toString()); + assertNull(e.getMessage()); + try + { + Type type = e.getType(); + log.error("unknown type: {}", type); + fail("unmapped type was resolved by enum: " + type); + } + catch (IllegalArgumentException ee) {} + assertEquals(new Integer(999999999), e.getCode()); + assertNull(e.getSubCode()); + assertNull(e.getUserTitle()); + assertNull(e.getUserMessage()); + assertNull(e.getTraceId()); + } + catch(Exception e) + { + fail("A wrong exception was thrown: " + e.toString()); + } + + + requestFactory.setBody( + "{\n" + + " \"error\":\n" + + " {\n" + + " \"message\": \"An unmapped Graph-API-Exception.\",\n" + + " \"type\": null,\n" + + " \"code\": 999999999\n" + + " }\n" + + "}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(UnmappedErrorException e) + { + log.debug("{}", e.toString()); + assertEquals("An unmapped Graph-API-Exception.", e.getMessage()); + assertNull(e.getType()); + assertEquals(new Integer(999999999), e.getCode()); + assertNull(e.getSubCode()); + assertNull(e.getUserTitle()); + assertNull(e.getUserMessage()); + assertNull(e.getTraceId()); + } + catch(Exception e) + { + fail("A wrong exception was thrown: " + e.toString()); + } + + + requestFactory.setBody( + "{\n" + + " \"error\":\n" + + " {\n" + + " \"message\": \"An unmapped Graph-API-Exception.\",\n" + + " \"code\": 999999999\n" + + " }\n" + + "}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(UnmappedErrorException e) + { + log.debug("{}", e.toString()); + assertEquals("An unmapped Graph-API-Exception.", e.getMessage()); + assertNull(e.getType()); + assertEquals(new Integer(999999999), e.getCode()); + assertNull(e.getSubCode()); + assertNull(e.getUserTitle()); + assertNull(e.getUserMessage()); + assertNull(e.getTraceId()); + } + catch(Exception e) + { + fail("A wrong exception was thrown: " + e.toString()); + } + } + + @Test + public void testInvlalidErrors() + { + log.info("testInvalidErrors"); + + + requestFactory.setBody( + "{\n" + + " \"error\":\n" + + " {\n" + + " \"message\": \"Not a Graph-Api-Exception.\",\n" + + " \"type\": \"Whatever\",\n" + + " \"code\": \"some string\"\n" + + " }\n" + + "}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(HttpClientErrorException e) + { + log.debug("{}", e.toString()); + } + catch(Exception e) + { + fail("A wrong exception was thrown: " + e.toString()); + } + + + requestFactory.setBody( + "{\n" + + " \"error\":\n" + + " {\n" + + " \"message\": \"Not a Graph-Api-Exception.\",\n" + + " \"type\": \"Whatever\",\n" + + " \"code\": 9.9\n" + + " }\n" + + "}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(HttpClientErrorException e) + { + log.debug("{}", e.toString()); + } + catch(Exception e) + { + fail("A wrong exception was thrown: " + e.toString()); + } + + + requestFactory.setBody( + "{\n" + + " \"error\":\n" + + " {\n" + + " \"message\": \"Not a Graph-Api-Exception.\",\n" + + " \"type\": \"Whatever\",\n" + + " \"code\": null\n" + + " }\n" + + "}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(HttpClientErrorException e) + { + log.debug("{}", e.toString()); + } + catch(Exception e) + { + fail("A wrong exception was thrown: " + e.toString()); + } + + + requestFactory.setBody( + "{\n" + + " \"error\":\n" + + " {\n" + + " \"message\": \"Not a Graph-Api-Exception.\",\n" + + " \"type\": \"Whatever\"\n" + + " }\n" + + "}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(HttpClientErrorException e) + { + log.debug("{}", e.toString()); + } + catch(Exception e) + { + fail("A wrong exception was thrown: " + e.toString()); + } + + + requestFactory.setBody("{\"error\":{\"message\":null}}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(HttpClientErrorException e) + { + log.debug("{}", e.toString()); + } + catch(Exception e) + { + fail("A wrong exception was thrown: " + e.toString()); + } + + + requestFactory.setBody("{\"error\":{\"type\":null}}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(HttpClientErrorException e) + { + log.debug("{}", e.toString()); + } + catch(Exception e) + { + fail("A wrong exception was thrown: " + e.toString()); + } + + + requestFactory.setBody("{\"error\":{\"code\":null}}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(HttpClientErrorException e) + { + log.debug("{}", e.toString()); + } + catch(Exception e) + { + fail("A wrong exception was thrown: " + e.toString()); + } + + + requestFactory.setBody("{\"error\":{}}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(HttpClientErrorException e) + { + log.debug("{}", e.toString()); + } + catch(Exception e) + { + fail("A wrong exception was thrown: " + e.toString()); + } + + + requestFactory.setBody("{\"error\":\"some message\"}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(HttpClientErrorException e) + { + log.debug("{}", e.toString()); + } + catch(Exception e) + { + fail("A wrong exception was thrown: " + e.toString()); + } + + + requestFactory.setBody("{\"error\":null}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(HttpClientErrorException e) + { + log.debug("{}", e.toString()); + } + catch(Exception e) + { + fail("A wrong exception was thrown: " + e.toString()); + } + + + requestFactory.setBody("{\"some filed\":\"some message\"}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(HttpClientErrorException e) + { + log.debug("{}", e.toString()); + } + catch(Exception e) + { + fail("A wrong exception was thrown: " + e.toString()); + } + + + requestFactory.setBody("{}"); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(HttpClientErrorException e) + { + log.debug("{}", e.toString()); + } + catch(Exception e) + { + fail("A wrong exception was thrown: " + e.toString()); + } + + + requestFactory.setBody(""); + + try + { + clientTemplate.getForObject("ANY", SOME.class); + fail("The expected exception was not thrown"); + } + catch(HttpClientErrorException e) + { + log.debug("{}", e.toString()); + } + catch(Exception e) + { + fail("A wrong exception was thrown: " + e.toString()); + } + } + + + @Before + public void setUp() + { + requestFactory = new MockClientHttpRequestFactory(); + requestFactory.setStatus(HttpStatus.BAD_REQUEST); + requestFactory.addHeader("Content-Type", "application/json"); + clientTemplate.setRequestFactory(requestFactory); + + clientTemplate.setErrorHandler( + new GraphApiErrorHandler( + (OAuth2ErrorHandler)clientTemplate.getErrorHandler() + ) + ); + + clientTemplate.setAccessTokenProvider(new AccessTokenProvider() + { + @Override + public OAuth2AccessToken obtainAccessToken( + OAuth2ProtectedResourceDetails details, + AccessTokenRequest parameters + ) + throws + UserRedirectRequiredException, + UserApprovalRequiredException, + AccessDeniedException + { + return new OAuth2AccessToken() { + + @Override + public Map getAdditionalInformation() + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Set getScope() + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public OAuth2RefreshToken getRefreshToken() + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public String getTokenType() + { + return OAUTH2_TYPE; + } + + @Override + public boolean isExpired() + { + return false; + } + + @Override + public Date getExpiration() + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public int getExpiresIn() + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public String getValue() + { + return "ANY"; + } + }; + } + + @Override + public boolean supportsResource(OAuth2ProtectedResourceDetails resource) + { + return true; + } + + @Override + public OAuth2AccessToken refreshAccessToken( + OAuth2ProtectedResourceDetails resource, + OAuth2RefreshToken refreshToken, + AccessTokenRequest request + ) + throws + UserRedirectRequiredException + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean supportsRefresh(OAuth2ProtectedResourceDetails resource) + { + return false; + } + }); + } + + + static class SOME + { + } +}