| // Copyright (C) 2019 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package com.google.gerrit.acceptance.server.quota; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| import static com.google.gerrit.server.quota.QuotaGroupDefinitions.REPOSITORY_SIZE_GROUP; |
| import static com.google.gerrit.server.quota.QuotaResponse.ok; |
| import static com.google.gerrit.testing.GerritJUnit.assertThrows; |
| import static org.mockito.ArgumentMatchers.anyLong; |
| import static org.mockito.ArgumentMatchers.eq; |
| import static org.mockito.Mockito.clearInvocations; |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.times; |
| import static org.mockito.Mockito.verify; |
| import static org.mockito.Mockito.when; |
| |
| import com.google.gerrit.acceptance.AbstractDaemonTest; |
| import com.google.gerrit.acceptance.UseLocalDisk; |
| import com.google.gerrit.extensions.config.FactoryModule; |
| import com.google.gerrit.server.CurrentUser; |
| import com.google.gerrit.server.quota.QuotaBackend; |
| import com.google.gerrit.server.quota.QuotaResponse; |
| import com.google.inject.Module; |
| import java.util.Collections; |
| import org.eclipse.jgit.api.errors.TooLargePackException; |
| import org.eclipse.jgit.api.errors.TransportException; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| @UseLocalDisk |
| public class RepositorySizeQuotaIT extends AbstractDaemonTest { |
| private static final QuotaBackend.WithResource quotaBackendWithResource = |
| mock(QuotaBackend.WithResource.class); |
| private static final QuotaBackend.WithUser quotaBackendWithUser = |
| mock(QuotaBackend.WithUser.class); |
| |
| @Override |
| public Module createModule() { |
| return new FactoryModule() { |
| @Override |
| public void configure() { |
| bind(QuotaBackend.class) |
| .toInstance( |
| new QuotaBackend() { |
| @Override |
| public WithUser currentUser() { |
| return quotaBackendWithUser; |
| } |
| |
| @Override |
| public WithUser user(CurrentUser user) { |
| return quotaBackendWithUser; |
| } |
| }); |
| } |
| }; |
| } |
| |
| @Before |
| public void setUp() { |
| clearInvocations(quotaBackendWithResource); |
| clearInvocations(quotaBackendWithUser); |
| } |
| |
| @Test |
| public void pushWithAvailableTokens() throws Exception { |
| // The push creates a pack that contains 325 bytes of uncompressed data. |
| // The data in the push contains sha and timestamps which are different on each test run. |
| // Due to it, the push's pack size varies after data compression and lead to a flaky tests |
| // if the amount of availableTokens doesn't cover all possible sizes. To avoid flakiness, we |
| // set availableTokens value large enough to cover all possible pack sizes. |
| when(quotaBackendWithResource.availableTokens(REPOSITORY_SIZE_GROUP)) |
| .thenReturn(singletonAggregation(ok(512L))); |
| when(quotaBackendWithResource.requestTokens(eq(REPOSITORY_SIZE_GROUP), anyLong())) |
| .thenReturn(singletonAggregation(ok())); |
| when(quotaBackendWithUser.project(project)).thenReturn(quotaBackendWithResource); |
| pushCommit(); |
| verify(quotaBackendWithResource, times(2)).availableTokens(REPOSITORY_SIZE_GROUP); |
| } |
| |
| @Test |
| public void pushWithNotSufficientTokens() throws Exception { |
| long availableTokens = 1L; |
| when(quotaBackendWithResource.availableTokens(REPOSITORY_SIZE_GROUP)) |
| .thenReturn(singletonAggregation(ok(availableTokens))); |
| when(quotaBackendWithUser.project(project)).thenReturn(quotaBackendWithResource); |
| assertThat(assertThrows(TooLargePackException.class, () -> pushCommit()).getMessage()) |
| .contains( |
| String.format( |
| "Pack exceeds the limit of %d bytes, rejecting the pack", availableTokens)); |
| } |
| |
| @Test |
| public void errorGettingAvailableTokens() throws Exception { |
| String msg = "quota error"; |
| when(quotaBackendWithResource.availableTokens(REPOSITORY_SIZE_GROUP)) |
| .thenReturn(singletonAggregation(QuotaResponse.error(msg))); |
| when(quotaBackendWithUser.project(project)).thenReturn(quotaBackendWithResource); |
| assertThrows(TransportException.class, () -> pushCommit()); |
| } |
| |
| private void pushCommit() throws Exception { |
| createCommitAndPush(testRepo, "refs/heads/master", "test 01", "file.test", "some content"); |
| } |
| |
| private static QuotaResponse.Aggregated singletonAggregation(QuotaResponse response) { |
| return QuotaResponse.Aggregated.create(Collections.singleton(response)); |
| } |
| } |