16
16
17
17
import static org .hamcrest .CoreMatchers .*;
18
18
import static org .hamcrest .CoreMatchers .notNullValue ;
19
+ import static org .hamcrest .Matchers .greaterThan ;
19
20
import static org .hamcrest .core .IsInstanceOf .instanceOf ;
20
21
21
22
// TODO: Auto-generated Javadoc
@@ -98,22 +99,14 @@ public void onError(IOException e, HttpURLConnection uc) throws IOException {
98
99
// getting an input stream in an error case should throw
99
100
IOException ioEx = Assert .assertThrows (IOException .class , () -> uc .getInputStream ());
100
101
101
- try (InputStream errorStream = uc .getErrorStream ()) {
102
- assertThat (errorStream , notNullValue ());
103
- String errorString = IOUtils .toString (errorStream , StandardCharsets .UTF_8 );
104
- assertThat (errorString , containsString ("Must have push access to repository" ));
105
- }
102
+ checkErrorMessageMatches (uc , "Must have push access to repository" );
106
103
107
104
// calling again should still error
108
105
ioEx = Assert .assertThrows (IOException .class , () -> uc .getInputStream ());
109
106
110
107
// calling again on a GitHubConnectorResponse should yield the same value
111
108
if (uc .toString ().contains ("GitHubConnectorResponseHttpUrlConnectionAdapter" )) {
112
- try (InputStream errorStream = uc .getErrorStream ()) {
113
- assertThat (errorStream , notNullValue ());
114
- String errorString = IOUtils .toString (errorStream , StandardCharsets .UTF_8 );
115
- assertThat (errorString , containsString ("Must have push access to repository" ));
116
- }
109
+ checkErrorMessageMatches (uc , "Must have push access to repository" );
117
110
} else {
118
111
try (InputStream errorStream = uc .getErrorStream ()) {
119
112
assertThat (errorStream , notNullValue ());
@@ -126,7 +119,7 @@ public void onError(IOException e, HttpURLConnection uc) throws IOException {
126
119
}
127
120
128
121
assertThat (uc .getHeaderFields (), instanceOf (Map .class ));
129
- assertThat (uc .getHeaderFields ().size (), Matchers . greaterThan (25 ));
122
+ assertThat (uc .getHeaderFields ().size (), greaterThan (25 ));
130
123
assertThat (uc .getHeaderField ("Status" ), equalTo ("403 Forbidden" ));
131
124
132
125
String key = uc .getHeaderFieldKey (1 );
@@ -349,16 +342,203 @@ public void onError(IOException e, HttpURLConnection uc) throws IOException {
349
342
assertThat (uc .getContentType (), equalTo ("application/json; charset=utf-8" ));
350
343
assertThat (uc .getContentLength (), equalTo (-1 ));
351
344
assertThat (uc .getHeaderFields (), instanceOf (Map .class ));
352
- assertThat (uc .getHeaderFields ().size (), Matchers . greaterThan (25 ));
345
+ assertThat (uc .getHeaderFields ().size (), greaterThan (25 ));
353
346
assertThat (uc .getHeaderField ("Status" ), equalTo ("403 Forbidden" ));
354
347
355
- try (InputStream errorStream = uc .getErrorStream ()) {
356
- assertThat (errorStream , notNullValue ());
357
- String errorString = IOUtils .toString (errorStream , StandardCharsets .UTF_8 );
358
- assertThat (errorString ,
359
- containsString (
360
- "You have exceeded a secondary rate limit. Please wait a few minutes before you try again" ));
361
- }
348
+ checkErrorMessageMatches (uc ,
349
+ "You have exceeded a secondary rate limit. Please wait a few minutes before you try again" );
350
+ AbuseLimitHandler .FAIL .onError (e , uc );
351
+ }
352
+ })
353
+ .build ();
354
+
355
+ gitHub .getMyself ();
356
+ assertThat (mockGitHub .getRequestCount (), equalTo (1 ));
357
+ try {
358
+ getTempRepository ();
359
+ fail ();
360
+ } catch (Exception e ) {
361
+ assertThat (e , instanceOf (HttpException .class ));
362
+ assertThat (e .getMessage (), equalTo ("Abuse limit reached" ));
363
+ }
364
+ assertThat (mockGitHub .getRequestCount (), equalTo (2 ));
365
+ }
366
+
367
+ /**
368
+ * This is making an assertion about the behaviour of the mock, so it's useful for making sure we're on the right
369
+ * mock, but should not be used to validate assumptions about the behaviour of the actual GitHub API.
370
+ */
371
+ private static void checkErrorMessageMatches (HttpURLConnection uc , String substring ) throws IOException {
372
+ try (InputStream errorStream = uc .getErrorStream ()) {
373
+ assertThat (errorStream , notNullValue ());
374
+ String errorString = IOUtils .toString (errorStream , StandardCharsets .UTF_8 );
375
+ assertThat (errorString , containsString (substring ));
376
+ }
377
+ }
378
+
379
+ /**
380
+ * Tests the behavior of the GitHub API client when the abuse limit handler is set to WAIT then the handler waits
381
+ * appropriately when secondary rate limits are encountered.
382
+ *
383
+ * @throws Exception
384
+ * if any error occurs during the test execution.
385
+ */
386
+ @ Test
387
+ public void testHandler_Wait_Secondary_Limits_Too_Many_Requests () throws Exception {
388
+ // Customized response that templates the date to keep things working
389
+ snapshotNotAllowed ();
390
+ final HttpURLConnection [] savedConnection = new HttpURLConnection [1 ];
391
+ gitHub = getGitHubBuilder ().withEndpoint (mockGitHub .apiServer ().baseUrl ())
392
+ .withAbuseLimitHandler (new AbuseLimitHandler () {
393
+ /**
394
+ * Overriding method because the actual method will wait for one minute causing slowness in unit
395
+ * tests
396
+ */
397
+ @ Override
398
+ public void onError (IOException e , HttpURLConnection uc ) throws IOException {
399
+ savedConnection [0 ] = uc ;
400
+ // Verify the test data is what we expected it to be for this test case
401
+ assertThat (uc .getDate (), Matchers .greaterThanOrEqualTo (new Date ().getTime () - 10000 ));
402
+ assertThat (uc .getExpiration (), equalTo (0L ));
403
+ assertThat (uc .getIfModifiedSince (), equalTo (0L ));
404
+ assertThat (uc .getLastModified (), equalTo (1581014017000L ));
405
+ assertThat (uc .getRequestMethod (), equalTo ("GET" ));
406
+ assertThat (uc .getResponseCode (), equalTo (429 ));
407
+ assertThat (uc .getResponseMessage (), containsString ("Many" ));
408
+ assertThat (uc .getURL ().toString (),
409
+ endsWith (
410
+ "/repos/hub4j-test-org/temp-testHandler_Wait_Secondary_Limits_Too_Many_Requests" ));
411
+ assertThat (uc .getContentLength (), equalTo (-1 ));
412
+ assertThat (uc .getHeaderFields (), instanceOf (Map .class ));
413
+ assertThat (uc .getHeaderField ("Status" ), equalTo ("429 Too Many Requests" ));
414
+ assertThat (uc .getHeaderField ("Retry-After" ), equalTo ("42" ));
415
+
416
+ checkErrorMessageMatches (uc ,
417
+ "You have exceeded a secondary rate limit. Please wait a few minutes before you try again" );
418
+ // Because we've overridden onError to bypass the wait, we don't cover the wait calculation
419
+ // logic
420
+ // Manually invoke it to make sure it's what we intended
421
+ long waitTime = parseWaitTime (uc );
422
+ assertThat (waitTime , equalTo (42 * 1000l ));
423
+
424
+ AbuseLimitHandler .FAIL .onError (e , uc );
425
+ }
426
+ })
427
+ .build ();
428
+
429
+ gitHub .getMyself ();
430
+ assertThat (mockGitHub .getRequestCount (), equalTo (1 ));
431
+ try {
432
+ getTempRepository ();
433
+ fail ();
434
+ } catch (Exception e ) {
435
+ assertThat (e , instanceOf (HttpException .class ));
436
+ assertThat (e .getMessage (), equalTo ("Abuse limit reached" ));
437
+ }
438
+ assertThat (mockGitHub .getRequestCount (), equalTo (2 ));
439
+ }
440
+
441
+ /**
442
+ * Tests the behavior of the GitHub API client when the abuse limit handler with a date retry.
443
+ *
444
+ * @throws Exception
445
+ * if any error occurs during the test execution.
446
+ */
447
+ @ Test
448
+ public void testHandler_Wait_Secondary_Limits_Too_Many_Requests_Date_Retry_After () throws Exception {
449
+ // Customized response that templates the date to keep things working
450
+ snapshotNotAllowed ();
451
+ final HttpURLConnection [] savedConnection = new HttpURLConnection [1 ];
452
+ gitHub = getGitHubBuilder ().withEndpoint (mockGitHub .apiServer ().baseUrl ())
453
+ .withAbuseLimitHandler (new AbuseLimitHandler () {
454
+ /**
455
+ * Overriding method because the actual method will wait for one minute causing slowness in unit
456
+ * tests
457
+ */
458
+ @ Override
459
+ public void onError (IOException e , HttpURLConnection uc ) throws IOException {
460
+ savedConnection [0 ] = uc ;
461
+ // Verify the test data is what we expected it to be for this test case
462
+ assertThat (uc .getRequestMethod (), equalTo ("GET" ));
463
+ assertThat (uc .getResponseCode (), equalTo (429 ));
464
+ assertThat (uc .getResponseMessage (), containsString ("Many" ));
465
+ assertThat (uc .getURL ().toString (),
466
+ endsWith (
467
+ "/repos/hub4j-test-org/temp-testHandler_Wait_Secondary_Limits_Too_Many_Requests_Date_Retry_After" ));
468
+ assertThat (uc .getContentLength (), equalTo (-1 ));
469
+ assertThat (uc .getHeaderField ("Status" ), equalTo ("429 Too Many Requests" ));
470
+ assertThat (uc .getHeaderField ("Retry-After" ), startsWith ("Mon" ));
471
+
472
+ checkErrorMessageMatches (uc ,
473
+ "You have exceeded a secondary rate limit. Please wait a few minutes before you try again" );
474
+
475
+ // Because we've overridden onError to bypass the wait, we don't cover the wait calculation
476
+ // logic
477
+ // Manually invoke it to make sure it's what we intended
478
+ long waitTime = parseWaitTime (uc );
479
+ // The exact value here will depend on when the test is run, but it should be positive, and huge
480
+ assertThat (waitTime , greaterThan (1000 * 1000l ));
481
+
482
+ AbuseLimitHandler .FAIL .onError (e , uc );
483
+ }
484
+ })
485
+ .build ();
486
+
487
+ gitHub .getMyself ();
488
+ assertThat (mockGitHub .getRequestCount (), equalTo (1 ));
489
+ try {
490
+ getTempRepository ();
491
+ fail ();
492
+ } catch (Exception e ) {
493
+ assertThat (e , instanceOf (HttpException .class ));
494
+ assertThat (e .getMessage (), equalTo ("Abuse limit reached" ));
495
+ }
496
+ assertThat (mockGitHub .getRequestCount (), equalTo (2 ));
497
+ }
498
+
499
+ /**
500
+ * Tests the behavior of the GitHub API client when the abuse limit handler with a no retry after header.
501
+ *
502
+ * @throws Exception
503
+ * if any error occurs during the test execution.
504
+ */
505
+ @ Test
506
+ public void testHandler_Wait_Secondary_Limits_Too_Many_Requests_No_Retry_After () throws Exception {
507
+ // Customized response that templates the date to keep things working
508
+ snapshotNotAllowed ();
509
+ final HttpURLConnection [] savedConnection = new HttpURLConnection [1 ];
510
+ gitHub = getGitHubBuilder ().withEndpoint (mockGitHub .apiServer ().baseUrl ())
511
+ .withAbuseLimitHandler (new AbuseLimitHandler () {
512
+ /**
513
+ * Overriding method because the actual method will wait for one minute causing slowness in unit
514
+ * tests
515
+ */
516
+ @ Override
517
+ public void onError (IOException e , HttpURLConnection uc ) throws IOException {
518
+ savedConnection [0 ] = uc ;
519
+ // Verify the test data is what we expected it to be for this test case
520
+ assertThat (uc .getRequestMethod (), equalTo ("GET" ));
521
+ assertThat (uc .getResponseCode (), equalTo (429 ));
522
+ assertThat (uc .getResponseMessage (), containsString ("Many" ));
523
+ assertThat (uc .getURL ().toString (),
524
+ endsWith (
525
+ "/repos/hub4j-test-org/temp-testHandler_Wait_Secondary_Limits_Too_Many_Requests_No_Retry_After" ));
526
+ assertThat (uc .getContentEncoding (), nullValue ());
527
+ assertThat (uc .getContentType (), equalTo ("application/json; charset=utf-8" ));
528
+ assertThat (uc .getContentLength (), equalTo (-1 ));
529
+ assertThat (uc .getHeaderFields (), instanceOf (Map .class ));
530
+ assertThat (uc .getHeaderField ("Status" ), equalTo ("429 Too Many Requests" ));
531
+ assertThat (uc .getHeaderField ("Retry-After" ), nullValue ());
532
+
533
+ checkErrorMessageMatches (uc ,
534
+ "You have exceeded a secondary rate limit. Please wait a few minutes before you try again" );
535
+
536
+ // Because we've overridden onError to bypass the wait, we don't cover the wait calculation
537
+ // logic
538
+ // Manually invoke it to make sure it's what we intended
539
+ long waitTime = parseWaitTime (uc );
540
+ assertThat (waitTime , greaterThan (60000l ));
541
+
362
542
AbuseLimitHandler .FAIL .onError (e , uc );
363
543
}
364
544
})
0 commit comments