Refactoring: moved all code concerned with error-handling in one package
[facebook-utils] / src / test / java / de / juplo / facebook / exceptions / GraphApiErrorHandlerTest.java
1 package de.juplo.facebook.exceptions;
2
3 import de.juplo.facebook.exceptions.GraphApiException.Type;
4 import java.util.Date;
5 import java.util.Map;
6 import java.util.Set;
7 import javax.annotation.Resource;
8 import static org.junit.Assert.assertEquals;
9 import static org.junit.Assert.assertNull;
10 import static org.junit.Assert.fail;
11 import org.junit.Before;
12 import org.junit.Test;
13 import org.junit.runner.RunWith;
14 import org.slf4j.Logger;
15 import org.slf4j.LoggerFactory;
16 import org.springframework.http.HttpStatus;
17 import org.springframework.security.access.AccessDeniedException;
18 import org.springframework.security.oauth2.client.OAuth2RestTemplate;
19 import org.springframework.security.oauth2.client.http.OAuth2ErrorHandler;
20 import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
21 import org.springframework.security.oauth2.client.resource.UserApprovalRequiredException;
22 import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException;
23 import org.springframework.security.oauth2.client.token.AccessTokenProvider;
24 import org.springframework.security.oauth2.client.token.AccessTokenRequest;
25 import org.springframework.security.oauth2.common.OAuth2AccessToken;
26 import static org.springframework.security.oauth2.common.OAuth2AccessToken.OAUTH2_TYPE;
27 import org.springframework.security.oauth2.common.OAuth2RefreshToken;
28 import org.springframework.test.context.ContextConfiguration;
29 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
30 import org.springframework.web.client.HttpClientErrorException;
31
32
33
34 /**
35  *
36  * @author Kai Moritz
37  */
38 @RunWith(SpringJUnit4ClassRunner.class)
39 @ContextConfiguration(
40   locations = {
41     "classpath:/spring/test-facebook-error-handler.xml"
42     })
43 public class GraphApiErrorHandlerTest
44 {
45   private static final Logger log =
46       LoggerFactory.getLogger(GraphApiErrorHandlerTest.class);
47
48   @Resource
49   private OAuth2RestTemplate clientTemplate;
50
51   private MockClientHttpRequestFactory requestFactory;
52
53
54   @Test
55   public void testError1()
56   {
57     log.info("testError1");
58
59
60     requestFactory.setBody(
61         "{\n" +
62         "  \"error\":\n" +
63         "  {\n" +
64         "    \"message\": \"An unknown error has occurred.\",\n" +
65         "    \"type\": \"OAuthException\",\n" +
66         "    \"code\": 1\n" +
67         "  }\n" +
68         "}");
69
70     try
71     {
72       clientTemplate.getForObject("ANY", SOME.class);
73       fail("The expected exception was not thrown");
74     }
75     catch(UnknownErrorException e)
76     {
77       log.debug("{}", e.toString());
78       assertEquals("invalid_request", e.getOAuth2ErrorCode());
79       assertEquals(new Integer(1), e.getCode());
80       assertEquals("An unknown error has occurred.", e.getMessage());
81       assertEquals(Type.OAuthException, e.getType());
82     }
83   }
84
85   @Test
86   public void testError2()
87   {
88     log.info("testError2");
89
90
91     requestFactory.setBody(
92         "{\n" +
93         "  \"error\":\n" +
94         "  {\n" +
95         "    \"message\": \"An unexpected error has occurred. Please retry your request later.\",\n" +
96         "    \"type\": \"OAuthException\",\n" +
97         "    \"code\": 2\n" +
98         "  }\n" +
99         "}");
100
101     try
102     {
103       clientTemplate.getForObject("ANY", SOME.class);
104       fail("The expected exception was not thrown");
105     }
106     catch(UnexpectedErrorException e)
107     {
108       log.debug("{}", e.toString());
109       assertEquals("invalid_request", e.getOAuth2ErrorCode());
110       assertEquals(new Integer(2), e.getCode());
111       assertEquals("An unexpected error has occurred. Please retry your request later.", e.getMessage());
112       assertEquals(Type.OAuthException, e.getType());
113     }
114   }
115
116   @Test
117   public void testError21()
118   {
119     log.info("testError21");
120
121
122     requestFactory.setBody(
123         "{\n" +
124         "  \"error\":\n" +
125         "  {\n" +
126         "    \"message\": \"(#21) Page ID 590408587650316 was migrated to page ID 1421620791415603.  Please update your API calls to the new ID\",\n" +
127         "    \"type\": \"OAuthException\",\n" +
128         "    \"code\": 21\n" +
129         "  }\n" +
130         "}");
131
132     try
133     {
134       clientTemplate.getForObject("ANY", SOME.class);
135       fail("The expected exception was not thrown");
136     }
137     catch(PageMigratedException e)
138     {
139       log.debug("{}", e.toString());
140       assertEquals("invalid_request", e.getOAuth2ErrorCode());
141       assertEquals(new Integer(21), e.getCode());
142       assertEquals("(#21) Page ID 590408587650316 was migrated to page ID 1421620791415603.  Please update your API calls to the new ID", e.getMessage());
143       assertEquals(Type.OAuthException, e.getType());
144     }
145   }
146
147   @Test
148   public void testError100()
149   {
150     log.info("testError100");
151
152
153     requestFactory.setBody(
154         "{\n" +
155         "  \"error\":\n" +
156         "  {\n" +
157         "    \"message\": \"Unsupported get request.\",\n" +
158         "    \"type\": \"GraphMethodException\",\n" +
159         "    \"code\": 100\n" +
160         "  }\n" +
161         "}");
162
163     try
164     {
165       clientTemplate.getForObject("ANY", SOME.class);
166       fail("The expected exception was not thrown");
167     }
168     catch(UnsupportedGetRequestException e)
169     {
170       log.debug("{}", e.toString());
171       assertEquals("invalid_request", e.getOAuth2ErrorCode());
172       assertEquals(new Integer(100), e.getCode());
173       assertEquals("Unsupported get request.", e.getMessage());
174       assertEquals(Type.GraphMethodException, e.getType());
175     }
176   }
177
178   @Test
179   public void testError104()
180   {
181     log.info("testError104");
182
183     requestFactory.setBody("{\"error\":{\"message\":\"An access token is required to request this resource.\",\"type\":\"OAuthException\",\"code\":104,\"fbtrace_id\":\"E2Jjkj5++LL\"}}");
184
185     try
186     {
187       clientTemplate.getForObject("ANY", SOME.class);
188       fail("The expected exception was not thrown");
189     }
190     catch(AccessTokenRequiredException e)
191     {
192       log.debug("{}", e.toString());
193       assertEquals("invalid_request", e.getOAuth2ErrorCode());
194       assertEquals(new Integer(104), e.getCode());
195       assertEquals("An access token is required to request this resource.", e.getMessage());
196       assertEquals(Type.OAuthException, e.getType());
197       assertEquals("E2Jjkj5++LL", e.getTraceId());
198     }
199   }
200
201   @Test
202   public void testError613()
203   {
204     log.info("testError613");
205
206
207     requestFactory.setBody(
208         "{\n" +
209         "  \"error\":\n" +
210         "  {\n" +
211         "    \"message\": \"(#613) Calls to stream have exceeded the rate of 600 calls per 600 seconds.\",\n" +
212         "    \"type\": \"OAuthException\",\n" +
213         "    \"code\": 613\n" +
214         "  }\n" +
215         "}");
216
217     try
218     {
219       clientTemplate.getForObject("ANY", SOME.class);
220       fail("The expected exception was not thrown");
221     }
222     catch(RateExceededException e)
223     {
224       log.debug("{}", e.toString());
225       assertEquals("invalid_request", e.getOAuth2ErrorCode());
226       assertEquals(new Integer(613), e.getCode());
227       assertEquals("(#613) Calls to stream have exceeded the rate of 600 calls per 600 seconds.", e.getMessage());
228       assertEquals(Type.OAuthException, e.getType());
229     }
230   }
231
232   @Test
233   public void testError2200()
234   {
235     requestFactory.setBody("{\"error\":{\"message\":\"(#2200) callback verification failed: \",\"type\":\"OAuthException\",\"code\":2200,\"fbtrace_id\":\"ESLjoZKvPXg\"}}");
236     
237     try
238     {
239       clientTemplate.getForObject("ANY", SOME.class);
240       fail("The expected exception was not thrown");
241     }
242     catch(CallbackVerificationFailedException e)
243     {
244       log.debug("{}", e.toString());
245       assertEquals("invalid_request", e.getOAuth2ErrorCode());
246       assertEquals(new Integer(2200), e.getCode());
247       assertEquals("(#2200) callback verification failed: ", e.getMessage());
248       assertEquals(Type.OAuthException, e.getType());
249       assertEquals("ESLjoZKvPXg", e.getTraceId());
250     }
251   }
252
253   @Test
254   public void testUnmappedError()
255   {
256     log.info("testUnmappedError");
257
258
259     requestFactory.setBody(
260         "{\n" +
261         "  \"error\":\n" +
262         "  {\n" +
263         "    \"message\": \"This error does not exist.\",\n" +
264         "    \"type\": \"NonexistentTypeException\",\n" +
265         "    \"code\": 999999999\n" +
266         "  }\n" +
267         "}");
268
269     try
270     {
271       clientTemplate.getForObject("ANY", SOME.class);
272       fail("The expected exception was not thrown");
273     }
274     catch(GraphApiException e)
275     {
276       log.debug("{}", e.toString());
277       assertEquals("invalid_request", e.getOAuth2ErrorCode());
278       assertEquals(new Integer(999999999), e.getCode());
279       assertEquals("This error does not exist.", e.getMessage());
280       try
281       {
282         Type type = e.getType();
283         log.error("unknown type: {}", type);
284         fail("unmapped type was resolved by enum: " + type);
285       }
286       catch (IllegalArgumentException ee) {}
287     }
288   }
289
290   @Test
291   public void testUnmappedErrors()
292   {
293     log.info("testUnmappedErrors");
294
295
296     requestFactory.setBody(
297         "{\n" +
298         "  \"error\":\n" +
299         "  {\n" +
300         "    \"message\": null,\n" +
301         "    \"type\": \"WhateverTypeException\",\n" +
302         "    \"code\": 999999999\n" +
303         "  }\n" +
304         "}");
305
306     try
307     {
308       clientTemplate.getForObject("ANY", SOME.class);
309       fail("The expected exception was not thrown");
310     }
311     catch(UnmappedErrorException e)
312     {
313       log.debug("{}", e.toString());
314       assertNull(e.getMessage());
315       try
316       {
317         Type type = e.getType();
318         log.error("unknown type: {}", type);
319         fail("unmapped type was resolved by enum: " + type);
320       }
321       catch (IllegalArgumentException ee) {}
322       assertEquals(new Integer(999999999), e.getCode());
323       assertNull(e.getSubCode());
324       assertNull(e.getUserTitle());
325       assertNull(e.getUserMessage());
326       assertNull(e.getTraceId());
327     }
328     catch(Exception e)
329     {
330       fail("A wrong exception was thrown: " + e.toString());
331     }
332
333
334     requestFactory.setBody(
335         "{\n" +
336         "  \"error\":\n" +
337         "  {\n" +
338         "    \"type\": \"WhateverTypeException\",\n" +
339         "    \"code\": 999999999\n" +
340         "  }\n" +
341         "}");
342
343     try
344     {
345       clientTemplate.getForObject("ANY", SOME.class);
346       fail("The expected exception was not thrown");
347     }
348     catch(UnmappedErrorException e)
349     {
350       log.debug("{}", e.toString());
351       assertNull(e.getMessage());
352       try
353       {
354         Type type = e.getType();
355         log.error("unknown type: {}", type);
356         fail("unmapped type was resolved by enum: " + type);
357       }
358       catch (IllegalArgumentException ee) {}
359       assertEquals(new Integer(999999999), e.getCode());
360       assertNull(e.getSubCode());
361       assertNull(e.getUserTitle());
362       assertNull(e.getUserMessage());
363       assertNull(e.getTraceId());
364     }
365     catch(Exception e)
366     {
367       fail("A wrong exception was thrown: " + e.toString());
368     }
369
370
371     requestFactory.setBody(
372         "{\n" +
373         "  \"error\":\n" +
374         "  {\n" +
375         "    \"message\": \"An unmapped Graph-API-Exception.\",\n" +
376         "    \"type\": null,\n" +
377         "    \"code\": 999999999\n" +
378         "  }\n" +
379         "}");
380
381     try
382     {
383       clientTemplate.getForObject("ANY", SOME.class);
384       fail("The expected exception was not thrown");
385     }
386     catch(UnmappedErrorException e)
387     {
388       log.debug("{}", e.toString());
389       assertEquals("An unmapped Graph-API-Exception.", e.getMessage());
390       assertNull(e.getType());
391       assertEquals(new Integer(999999999), e.getCode());
392       assertNull(e.getSubCode());
393       assertNull(e.getUserTitle());
394       assertNull(e.getUserMessage());
395       assertNull(e.getTraceId());
396     }
397     catch(Exception e)
398     {
399       fail("A wrong exception was thrown: " + e.toString());
400     }
401
402
403     requestFactory.setBody(
404         "{\n" +
405         "  \"error\":\n" +
406         "  {\n" +
407         "    \"message\": \"An unmapped Graph-API-Exception.\",\n" +
408         "    \"code\": 999999999\n" +
409         "  }\n" +
410         "}");
411
412     try
413     {
414       clientTemplate.getForObject("ANY", SOME.class);
415       fail("The expected exception was not thrown");
416     }
417     catch(UnmappedErrorException e)
418     {
419       log.debug("{}", e.toString());
420       assertEquals("An unmapped Graph-API-Exception.", e.getMessage());
421       assertNull(e.getType());
422       assertEquals(new Integer(999999999), e.getCode());
423       assertNull(e.getSubCode());
424       assertNull(e.getUserTitle());
425       assertNull(e.getUserMessage());
426       assertNull(e.getTraceId());
427     }
428     catch(Exception e)
429     {
430       fail("A wrong exception was thrown: " + e.toString());
431     }
432   }
433
434   @Test
435   public void testInvlalidErrors()
436   {
437     log.info("testInvalidErrors");
438
439
440     requestFactory.setBody(
441         "{\n" +
442         "  \"error\":\n" +
443         "  {\n" +
444         "    \"message\": \"Not a Graph-Api-Exception.\",\n" +
445         "    \"type\": \"Whatever\",\n" +
446         "    \"code\": \"some string\"\n" +
447         "  }\n" +
448         "}");
449
450     try
451     {
452       clientTemplate.getForObject("ANY", SOME.class);
453       fail("The expected exception was not thrown");
454     }
455     catch(HttpClientErrorException e)
456     {
457       log.debug("{}", e.toString());
458     }
459     catch(Exception e)
460     {
461       fail("A wrong exception was thrown: " + e.toString());
462     }
463
464
465     requestFactory.setBody(
466         "{\n" +
467         "  \"error\":\n" +
468         "  {\n" +
469         "    \"message\": \"Not a Graph-Api-Exception.\",\n" +
470         "    \"type\": \"Whatever\",\n" +
471         "    \"code\": 9.9\n" +
472         "  }\n" +
473         "}");
474
475     try
476     {
477       clientTemplate.getForObject("ANY", SOME.class);
478       fail("The expected exception was not thrown");
479     }
480     catch(HttpClientErrorException e)
481     {
482       log.debug("{}", e.toString());
483     }
484     catch(Exception e)
485     {
486       fail("A wrong exception was thrown: " + e.toString());
487     }
488
489
490     requestFactory.setBody(
491         "{\n" +
492         "  \"error\":\n" +
493         "  {\n" +
494         "    \"message\": \"Not a Graph-Api-Exception.\",\n" +
495         "    \"type\": \"Whatever\",\n" +
496         "    \"code\": null\n" +
497         "  }\n" +
498         "}");
499
500     try
501     {
502       clientTemplate.getForObject("ANY", SOME.class);
503       fail("The expected exception was not thrown");
504     }
505     catch(HttpClientErrorException e)
506     {
507       log.debug("{}", e.toString());
508     }
509     catch(Exception e)
510     {
511       fail("A wrong exception was thrown: " + e.toString());
512     }
513
514
515     requestFactory.setBody(
516         "{\n" +
517         "  \"error\":\n" +
518         "  {\n" +
519         "    \"message\": \"Not a Graph-Api-Exception.\",\n" +
520         "    \"type\": \"Whatever\"\n" +
521         "  }\n" +
522         "}");
523
524     try
525     {
526       clientTemplate.getForObject("ANY", SOME.class);
527       fail("The expected exception was not thrown");
528     }
529     catch(HttpClientErrorException e)
530     {
531       log.debug("{}", e.toString());
532     }
533     catch(Exception e)
534     {
535       fail("A wrong exception was thrown: " + e.toString());
536     }
537
538
539     requestFactory.setBody("{\"error\":{\"message\":null}}");
540
541     try
542     {
543       clientTemplate.getForObject("ANY", SOME.class);
544       fail("The expected exception was not thrown");
545     }
546     catch(HttpClientErrorException e)
547     {
548       log.debug("{}", e.toString());
549     }
550     catch(Exception e)
551     {
552       fail("A wrong exception was thrown: " + e.toString());
553     }
554
555
556     requestFactory.setBody("{\"error\":{\"type\":null}}");
557
558     try
559     {
560       clientTemplate.getForObject("ANY", SOME.class);
561       fail("The expected exception was not thrown");
562     }
563     catch(HttpClientErrorException e)
564     {
565       log.debug("{}", e.toString());
566     }
567     catch(Exception e)
568     {
569       fail("A wrong exception was thrown: " + e.toString());
570     }
571
572
573     requestFactory.setBody("{\"error\":{\"code\":null}}");
574
575     try
576     {
577       clientTemplate.getForObject("ANY", SOME.class);
578       fail("The expected exception was not thrown");
579     }
580     catch(HttpClientErrorException e)
581     {
582       log.debug("{}", e.toString());
583     }
584     catch(Exception e)
585     {
586       fail("A wrong exception was thrown: " + e.toString());
587     }
588
589
590     requestFactory.setBody("{\"error\":{}}");
591
592     try
593     {
594       clientTemplate.getForObject("ANY", SOME.class);
595       fail("The expected exception was not thrown");
596     }
597     catch(HttpClientErrorException e)
598     {
599       log.debug("{}", e.toString());
600     }
601     catch(Exception e)
602     {
603       fail("A wrong exception was thrown: " + e.toString());
604     }
605
606
607     requestFactory.setBody("{\"error\":\"some message\"}");
608
609     try
610     {
611       clientTemplate.getForObject("ANY", SOME.class);
612       fail("The expected exception was not thrown");
613     }
614     catch(HttpClientErrorException e)
615     {
616       log.debug("{}", e.toString());
617     }
618     catch(Exception e)
619     {
620       fail("A wrong exception was thrown: " + e.toString());
621     }
622
623
624     requestFactory.setBody("{\"error\":null}");
625
626     try
627     {
628       clientTemplate.getForObject("ANY", SOME.class);
629       fail("The expected exception was not thrown");
630     }
631     catch(HttpClientErrorException e)
632     {
633       log.debug("{}", e.toString());
634     }
635     catch(Exception e)
636     {
637       fail("A wrong exception was thrown: " + e.toString());
638     }
639
640
641     requestFactory.setBody("{\"some filed\":\"some message\"}");
642
643     try
644     {
645       clientTemplate.getForObject("ANY", SOME.class);
646       fail("The expected exception was not thrown");
647     }
648     catch(HttpClientErrorException e)
649     {
650       log.debug("{}", e.toString());
651     }
652     catch(Exception e)
653     {
654       fail("A wrong exception was thrown: " + e.toString());
655     }
656
657
658     requestFactory.setBody("{}");
659
660     try
661     {
662       clientTemplate.getForObject("ANY", SOME.class);
663       fail("The expected exception was not thrown");
664     }
665     catch(HttpClientErrorException e)
666     {
667       log.debug("{}", e.toString());
668     }
669     catch(Exception e)
670     {
671       fail("A wrong exception was thrown: " + e.toString());
672     }
673
674
675     requestFactory.setBody("");
676
677     try
678     {
679       clientTemplate.getForObject("ANY", SOME.class);
680       fail("The expected exception was not thrown");
681     }
682     catch(HttpClientErrorException e)
683     {
684       log.debug("{}", e.toString());
685     }
686     catch(Exception e)
687     {
688       fail("A wrong exception was thrown: " + e.toString());
689     }
690   }
691
692
693   @Before
694   public void setUp()
695   {
696     requestFactory = new MockClientHttpRequestFactory();
697     requestFactory.setStatus(HttpStatus.BAD_REQUEST);
698     requestFactory.addHeader("Content-Type", "application/json");
699     clientTemplate.setRequestFactory(requestFactory);
700
701     clientTemplate.setErrorHandler(
702         new GraphApiErrorHandler(
703             (OAuth2ErrorHandler)clientTemplate.getErrorHandler()
704             )
705         );
706
707     clientTemplate.setAccessTokenProvider(new AccessTokenProvider()
708     {
709       @Override
710       public OAuth2AccessToken obtainAccessToken(
711           OAuth2ProtectedResourceDetails details,
712           AccessTokenRequest parameters
713           )
714           throws
715             UserRedirectRequiredException,
716             UserApprovalRequiredException,
717             AccessDeniedException
718       {
719         return new OAuth2AccessToken() {
720
721           @Override
722           public Map<String, Object> getAdditionalInformation()
723           {
724             throw new UnsupportedOperationException("Not supported yet.");
725           }
726
727           @Override
728           public Set<String> getScope()
729           {
730             throw new UnsupportedOperationException("Not supported yet.");
731           }
732
733           @Override
734           public OAuth2RefreshToken getRefreshToken()
735           {
736             throw new UnsupportedOperationException("Not supported yet.");
737           }
738
739           @Override
740           public String getTokenType()
741           {
742             return OAUTH2_TYPE;
743           }
744
745           @Override
746           public boolean isExpired()
747           {
748             return false;
749           }
750
751           @Override
752           public Date getExpiration()
753           {
754             throw new UnsupportedOperationException("Not supported yet.");
755           }
756
757           @Override
758           public int getExpiresIn()
759           {
760             throw new UnsupportedOperationException("Not supported yet.");
761           }
762
763           @Override
764           public String getValue()
765           {
766             return "ANY";
767           }
768         };
769       }
770
771       @Override
772       public boolean supportsResource(OAuth2ProtectedResourceDetails resource)
773       {
774         return true;
775       }
776
777       @Override
778       public OAuth2AccessToken refreshAccessToken(
779           OAuth2ProtectedResourceDetails resource,
780           OAuth2RefreshToken refreshToken,
781           AccessTokenRequest request
782           )
783           throws
784             UserRedirectRequiredException
785       {
786         throw new UnsupportedOperationException("Not supported yet.");
787       }
788
789       @Override
790       public boolean supportsRefresh(OAuth2ProtectedResourceDetails resource)
791       {
792         return false;
793       }
794     });
795   }
796
797
798   static class SOME
799   {
800   }
801 }