3 * Copyright (C) 2009-2023 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.alm.client.github;
22 import com.tngtech.java.junit.dataprovider.DataProvider;
23 import com.tngtech.java.junit.dataprovider.DataProviderRunner;
24 import com.tngtech.java.junit.dataprovider.UseDataProvider;
26 import java.time.temporal.ChronoUnit;
27 import org.junit.Rule;
28 import org.junit.Test;
29 import org.junit.runner.RunWith;
30 import org.kohsuke.github.GHRateLimit;
31 import org.slf4j.event.Level;
32 import org.sonar.api.testfixtures.log.LogTester;
34 import static java.lang.String.format;
35 import static java.time.Instant.now;
36 import static org.assertj.core.api.Assertions.assertThat;
37 import static org.mockito.Mockito.mock;
38 import static org.mockito.Mockito.when;
39 import static org.sonar.alm.client.github.RatioBasedRateLimitChecker.RATE_RATIO_EXCEEDED_MESSAGE;
41 @RunWith(DataProviderRunner.class)
42 public class RatioBasedRateLimitCheckerTest {
45 public LogTester logTester = new LogTester();
46 private static final long MILLIS_BEFORE_RESET = 100L;
47 RatioBasedRateLimitChecker ratioBasedRateLimitChecker = new RatioBasedRateLimitChecker();
50 public static Object[][] rates() {
51 return new Object[][] {
52 {10000, 100000, false},
53 {10000, 10000, false},
64 @UseDataProvider("rates")
65 public void checkRateLimit(int limit, int remaining, boolean rateLimitShouldBeExceeded) throws InterruptedException {
66 GHRateLimit.Record record = mock();
67 when(record.getLimit()).thenReturn(limit);
68 when(record.getRemaining()).thenReturn(remaining);
69 when(record.getResetDate()).thenReturn(Date.from(now().plus(100, ChronoUnit.MILLIS)));
71 long start = System.currentTimeMillis();
72 boolean result = ratioBasedRateLimitChecker.checkRateLimit(record, 10);
73 long stop = System.currentTimeMillis();
74 long totalTime = stop - start;
76 if (rateLimitShouldBeExceeded) {
77 assertThat(result).isTrue();
78 assertThat(stop).isGreaterThanOrEqualTo(record.getResetDate().getTime());
79 assertThat(logTester.logs(Level.WARN)).contains(
80 format(RATE_RATIO_EXCEEDED_MESSAGE.replaceAll("\\{\\}", "%s"), limit - remaining, limit));
82 assertThat(result).isFalse();
83 assertThat(totalTime).isLessThan(MILLIS_BEFORE_RESET);
84 assertThat(logTester.logs(Level.WARN)).isEmpty();