blob: c71db41ecdca1366097883fe402e84e3f95153b5 [file] [log] [blame]
// 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.plugins.checks.acceptance.api;
import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.git.testing.CommitSubject.assertCommit;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.acceptance.UseClockStep;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.plugins.checks.CheckerQuery;
import com.google.gerrit.plugins.checks.CheckerUuid;
import com.google.gerrit.plugins.checks.acceptance.AbstractCheckersTest;
import com.google.gerrit.plugins.checks.acceptance.testsuite.CheckerOperations.PerCheckerOperations;
import com.google.gerrit.plugins.checks.acceptance.testsuite.CheckerTestData;
import com.google.gerrit.plugins.checks.api.BlockingCondition;
import com.google.gerrit.plugins.checks.api.CheckerInfo;
import com.google.gerrit.plugins.checks.api.CheckerInput;
import com.google.gerrit.plugins.checks.api.CheckerStatus;
import com.google.gerrit.plugins.checks.db.CheckersByRepositoryNotes;
import com.google.gerrit.testing.ConfigSuite;
import com.google.gerrit.testing.TestTimeUtil;
import com.google.inject.Inject;
import java.sql.Timestamp;
import org.eclipse.jgit.lib.Config;
import org.junit.Test;
@UseClockStep(startAtEpoch = true)
public class CreateCheckerIT extends AbstractCheckersTest {
private static final int MAX_INDEX_TERMS = 10;
@Inject private RequestScopeOperations requestScopeOperations;
@Inject private ProjectOperations projectOperations;
@ConfigSuite.Default
public static Config defaultConfig() {
Config cfg = new Config();
cfg.setInt("index", null, "maxTerms", MAX_INDEX_TERMS);
return cfg;
}
@Test
public void createChecker() throws Exception {
Project.NameKey repositoryName = projectOperations.newProject().create();
Timestamp expectedCreationTimestamp = TestTimeUtil.getCurrentTimestamp();
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.name = "My Checker";
input.repository = repositoryName.get();
CheckerInfo info = checkersApi.create(input).get();
assertThat(info.uuid).isEqualTo("test:my-checker");
assertThat(info.name).isEqualTo("My Checker");
assertThat(info.description).isNull();
assertThat(info.url).isNull();
assertThat(info.repository).isEqualTo(input.repository);
assertThat(info.status).isEqualTo(CheckerStatus.ENABLED);
assertThat(info.blocking).isEmpty();
assertThat(info.query).isEqualTo("status:open");
assertThat(info.created).isEqualTo(expectedCreationTimestamp);
assertThat(info.updated).isEqualTo(info.created);
PerCheckerOperations perCheckerOps = checkerOperations.checker(info.uuid);
assertCommit(
perCheckerOps.commit(), "Create checker", info.created, perCheckerOps.get().getRefState());
assertThat(checkerOperations.sha1sOfRepositoriesWithCheckers())
.containsExactly(CheckersByRepositoryNotes.computeRepositorySha1(repositoryName));
assertThat(checkerOperations.checkersOf(repositoryName))
.containsExactly(CheckerUuid.parse(info.uuid));
}
@Test
public void createCheckerWithDescription() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.name = "My Checker";
input.description = "some description";
input.repository = allProjects.get();
CheckerInfo info = checkersApi.create(input).get();
assertThat(info.description).isEqualTo(input.description);
PerCheckerOperations perCheckerOps = checkerOperations.checker(info.uuid);
assertCommit(
perCheckerOps.commit(), "Create checker", info.created, perCheckerOps.get().getRefState());
}
@Test
public void createCheckerWithUrl() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.name = "My Checker";
input.url = "http://example.com/my-checker";
input.repository = allProjects.get();
CheckerInfo info = checkersApi.create(input).get();
assertThat(info.url).isEqualTo(input.url);
PerCheckerOperations perCheckerOps = checkerOperations.checker(info.uuid);
assertCommit(
perCheckerOps.commit(), "Create checker", info.created, perCheckerOps.get().getRefState());
}
@Test
public void createCheckerWithoutNameFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.repository = allProjects.get();
BadRequestException thrown =
assertThrows(BadRequestException.class, () -> checkersApi.create(input));
assertThat(thrown).hasMessageThat().contains("name is required");
}
@Test
public void createCheckerNameIsTrimmed() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.name = " My Checker ";
input.repository = allProjects.get();
CheckerInfo info = checkersApi.create(input).get();
assertThat(info.name).isEqualTo("My Checker");
PerCheckerOperations perCheckerOps = checkerOperations.checker(info.uuid);
assertCommit(
perCheckerOps.commit(), "Create checker", info.created, perCheckerOps.get().getRefState());
}
@Test
public void createCheckerDescriptionIsTrimmed() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.name = "My Checker";
input.description = " some description ";
input.repository = allProjects.get();
CheckerInfo info = checkersApi.create(input).get();
assertThat(info.description).isEqualTo("some description");
PerCheckerOperations perCheckerOps = checkerOperations.checker(info.uuid);
assertCommit(
perCheckerOps.commit(), "Create checker", info.created, perCheckerOps.get().getRefState());
}
@Test
public void createCheckerUrlIsTrimmed() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.name = "My Checker";
input.url = " http://example.com/my-checker ";
input.repository = allProjects.get();
CheckerInfo info = checkersApi.create(input).get();
assertThat(info.url).isEqualTo("http://example.com/my-checker");
PerCheckerOperations perCheckerOps = checkerOperations.checker(info.uuid);
assertCommit(
perCheckerOps.commit(), "Create checker", info.created, perCheckerOps.get().getRefState());
}
@Test
public void createCheckerRepositoryIsTrimmed() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.name = "My Checker";
input.repository = " " + allProjects.get() + " ";
CheckerInfo info = checkersApi.create(input).get();
assertThat(info.repository).isEqualTo(allProjects.get());
PerCheckerOperations perCheckerOps = checkerOperations.checker(info.uuid);
assertCommit(
perCheckerOps.commit(), "Create checker", info.created, perCheckerOps.get().getRefState());
}
@Test
public void createCheckerWithInvalidUrlFails() throws Exception {
CheckerUuid checkerUuid = checkerOperations.newChecker().name("my-checker").create();
CheckerInput input = new CheckerInput();
input.url = CheckerTestData.INVALID_URL;
BadRequestException thrown =
assertThrows(BadRequestException.class, () -> checkersApi.id(checkerUuid).update(input));
assertThat(thrown).hasMessageThat().contains("only http/https URLs supported: " + input.url);
}
@Test
public void createCheckersWithSameName() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.name = "My Checker";
input.repository = allProjects.get();
CheckerInfo info1 = checkersApi.create(input).get();
assertThat(info1.name).isEqualTo(input.name);
input.uuid = "test:another-checker";
CheckerInfo info2 = checkersApi.create(input).get();
assertThat(info2.name).isEqualTo(input.name);
assertThat(info2.uuid).isNotEqualTo(info1.uuid);
}
@Test
public void createCheckerWithExistingUuidFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.name = "My Checker";
input.repository = allProjects.get();
checkersApi.create(input).get();
ResourceConflictException thrown =
assertThrows(ResourceConflictException.class, () -> checkersApi.create(input));
assertThat(thrown).hasMessageThat().contains("Checker test:my-checker already exists");
}
@Test
public void createCheckerWithoutUuidFails() throws Exception {
CheckerInput input = new CheckerInput();
input.name = "My Checker";
input.repository = allProjects.get();
BadRequestException thrown =
assertThrows(BadRequestException.class, () -> checkersApi.create(input));
assertThat(thrown).hasMessageThat().contains("uuid is required");
}
@Test
public void createCheckerWithEmptyUuidFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "";
input.name = "My Checker";
input.repository = allProjects.get();
BadRequestException thrown =
assertThrows(BadRequestException.class, () -> checkersApi.create(input));
assertThat(thrown).hasMessageThat().contains("uuid is required");
}
@Test
public void createCheckerWithEmptyUuidAfterTrimFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = " ";
input.name = "My Checker";
input.repository = allProjects.get();
BadRequestException thrown =
assertThrows(BadRequestException.class, () -> checkersApi.create(input));
assertThat(thrown).hasMessageThat().contains("invalid uuid: ");
}
@Test
public void createCheckerWithInvalidUuidFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = CheckerTestData.INVALID_UUID;
input.name = "My Checker";
input.repository = allProjects.get();
BadRequestException thrown =
assertThrows(BadRequestException.class, () -> checkersApi.create(input));
assertThat(thrown).hasMessageThat().contains("invalid uuid: " + input.uuid);
}
@Test
public void createCheckerWithoutRepositoryFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.name = "My Checker";
BadRequestException thrown =
assertThrows(BadRequestException.class, () -> checkersApi.create(input));
assertThat(thrown).hasMessageThat().contains("repository is required");
}
@Test
public void createCheckerWithEmptyRepositoryFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.name = "My Checker";
input.repository = "";
BadRequestException thrown =
assertThrows(BadRequestException.class, () -> checkersApi.create(input));
assertThat(thrown).hasMessageThat().contains("repository is required");
}
@Test
public void createCheckerWithEmptyRepositoryAfterTrimFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.name = "My Checker";
input.repository = " ";
BadRequestException thrown =
assertThrows(BadRequestException.class, () -> checkersApi.create(input));
assertThat(thrown).hasMessageThat().contains("repository is required");
}
@Test
public void createCheckerWithNonExistingRepositoryFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.name = "My Checker";
input.repository = "non-existing";
UnprocessableEntityException thrown =
assertThrows(UnprocessableEntityException.class, () -> checkersApi.create(input));
assertThat(thrown).hasMessageThat().contains("repository non-existing not found");
}
@Test
public void createDisabledChecker() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.name = "My Checker";
input.repository = allProjects.get();
input.status = CheckerStatus.DISABLED;
CheckerInfo info = checkersApi.create(input).get();
assertThat(info.status).isEqualTo(CheckerStatus.DISABLED);
}
@Test
public void createCheckerWithBlockingConditions() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.name = "My Checker";
input.repository = allProjects.get();
input.blocking = ImmutableSet.of(BlockingCondition.STATE_NOT_PASSING);
CheckerInfo info = checkersApi.create(input).get();
assertThat(info.blocking).containsExactly(BlockingCondition.STATE_NOT_PASSING);
}
@Test
public void createCheckerWithQuery() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.name = "My Checker";
input.repository = allProjects.get();
input.query = "f:foo";
CheckerInfo info = checkersApi.create(input).get();
assertThat(info.query).isEqualTo("f:foo");
}
@Test
public void createCheckerWithEmptyQuery() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.name = "My Checker";
input.repository = allProjects.get();
input.query = "";
CheckerInfo info = checkersApi.create(input).get();
assertThat(info.query).isNull();
}
@Test
public void createCheckerWithEmptyQueryAfterTrim() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.name = "My Checker";
input.repository = allProjects.get();
input.query = " ";
CheckerInfo info = checkersApi.create(input).get();
assertThat(info.query).isNull();
}
@Test
public void createCheckerWithUnsupportedOperatorInQueryFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.name = "My Checker";
input.repository = allProjects.get();
input.query = CheckerTestData.QUERY_WITH_UNSUPPORTED_OPERATOR;
BadRequestException thrown =
assertThrows(BadRequestException.class, () -> checkersApi.create(input).get());
assertThat(thrown)
.hasMessageThat()
.isEqualTo("Unsupported operator: " + CheckerTestData.UNSUPPORTED_OPERATOR);
}
@Test
public void createCheckerWithInvalidQueryFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.name = "My Checker";
input.repository = allProjects.get();
input.query = CheckerTestData.INVALID_QUERY;
BadRequestException thrown =
assertThrows(BadRequestException.class, () -> checkersApi.create(input).get());
assertThat(thrown).hasMessageThat().contains("Invalid query: " + input.query);
}
@Test
public void createCheckerWithTooLongQueryFails() throws Exception {
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.name = "My Checker";
input.repository = allProjects.get();
input.query = CheckerTestData.longQueryWithSupportedOperators(MAX_INDEX_TERMS * 2);
assertThat(CheckerQuery.clean(input.query)).isEqualTo(input.query);
BadRequestException thrown =
assertThrows(BadRequestException.class, () -> checkersApi.create(input).get());
assertThat(thrown)
.hasMessageThat()
.isEqualTo(
"change query of checker "
+ input.uuid
+ " is invalid: "
+ input.query
+ " (too many terms in query: 42 terms (max = 10))");
}
@Test
public void createMultipleCheckers() throws Exception {
Project.NameKey repositoryName1 = projectOperations.newProject().create();
Project.NameKey repositoryName2 = projectOperations.newProject().create();
CheckerUuid checkerUuid1 = checkerOperations.newChecker().repository(repositoryName1).create();
CheckerUuid checkerUuid2 = checkerOperations.newChecker().repository(repositoryName1).create();
CheckerUuid checkerUuid3 = checkerOperations.newChecker().repository(repositoryName1).create();
CheckerUuid checkerUuid4 = checkerOperations.newChecker().repository(repositoryName2).create();
CheckerUuid checkerUuid5 = checkerOperations.newChecker().repository(repositoryName2).create();
assertThat(checkerOperations.sha1sOfRepositoriesWithCheckers())
.containsExactly(
CheckersByRepositoryNotes.computeRepositorySha1(repositoryName1),
CheckersByRepositoryNotes.computeRepositorySha1(repositoryName2));
assertThat(checkerOperations.checkersOf(repositoryName1))
.containsExactly(checkerUuid1, checkerUuid2, checkerUuid3);
assertThat(checkerOperations.checkersOf(repositoryName2))
.containsExactly(checkerUuid4, checkerUuid5);
}
@Test
public void createCheckerWithoutAdministrateCheckersCapabilityFails() throws Exception {
requestScopeOperations.setApiUser(user.id());
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.repository = allProjects.get();
AuthException thrown = assertThrows(AuthException.class, () -> checkersApi.create(input));
assertThat(thrown)
.hasMessageThat()
.contains("administrateCheckers for plugin checks not permitted");
}
@Test
public void createCheckerAnonymouslyFails() throws Exception {
requestScopeOperations.setApiUserAnonymous();
CheckerInput input = new CheckerInput();
input.uuid = "test:my-checker";
input.repository = allProjects.get();
AuthException thrown = assertThrows(AuthException.class, () -> checkersApi.create(input));
assertThat(thrown).hasMessageThat().contains("Authentication required");
}
}