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