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