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