blob: 045f01b4a5dcfca9e564dc86ce9f94800e836e4f [file] [log] [blame]
// Copyright (C) 2021 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.codeowners.acceptance.api;
import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.server.project.ProjectCache.illegalState;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static com.google.gerrit.truth.OptionalSubject.assertThat;
import com.google.common.collect.ImmutableList;
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.BranchNameKey;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.plugins.codeowners.acceptance.AbstractCodeOwnersIT;
import com.google.gerrit.plugins.codeowners.api.CodeOwnerProjectConfigInfo;
import com.google.gerrit.plugins.codeowners.api.CodeOwnerProjectConfigInput;
import com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginConfiguration;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.restapi.project.DeleteRef;
import com.google.inject.Inject;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Before;
import org.junit.Test;
/**
* Acceptance test for the {@link
* com.google.gerrit.plugins.codeowners.restapi.PutCodeOwnerProjectConfig} REST endpoint.
*
* <p>Further tests for the {@link
* com.google.gerrit.plugins.codeowners.restapi.PutCodeOwnerProjectConfig} REST endpoint that
* require using the REST API are implemented in {@link
* com.google.gerrit.plugins.codeowners.acceptance.restapi.PutCodeOwnerProjectConfigRestIT}.
*/
public class PutCodeOwnerProjectConfigIT extends AbstractCodeOwnersIT {
@Inject private RequestScopeOperations requestScopeOperations;
@Inject private ProjectOperations projectOperations;
@Inject private DeleteRef deleteRef;
private CodeOwnersPluginConfiguration codeOwnersPluginConfiguration;
@Before
public void setup() throws Exception {
codeOwnersPluginConfiguration =
plugin.getSysInjector().getInstance(CodeOwnersPluginConfiguration.class);
}
@Test
public void requiresCallerToBeProjectOwner() throws Exception {
requestScopeOperations.setApiUser(user.id());
AuthException authException =
assertThrows(
AuthException.class,
() ->
projectCodeOwnersApiFactory
.project(project)
.updateConfig(new CodeOwnerProjectConfigInput()));
assertThat(authException).hasMessageThat().isEqualTo("write refs/meta/config not permitted");
}
@Test
public void disableAndReenableCodeOwnersFunctionality() throws Exception {
assertThat(codeOwnersPluginConfiguration.isDisabled(project)).isFalse();
CodeOwnerProjectConfigInput input = new CodeOwnerProjectConfigInput();
input.disabled = true;
CodeOwnerProjectConfigInfo updatedConfig =
projectCodeOwnersApiFactory.project(project).updateConfig(input);
assertThat(updatedConfig.status.disabled).isTrue();
assertThat(codeOwnersPluginConfiguration.isDisabled(project)).isTrue();
input.disabled = false;
updatedConfig = projectCodeOwnersApiFactory.project(project).updateConfig(input);
assertThat(updatedConfig.status.disabled).isNull();
assertThat(codeOwnersPluginConfiguration.isDisabled(project)).isFalse();
}
@Test
public void setDisabledBranches() throws Exception {
BranchNameKey masterBranch = BranchNameKey.create(project, "master");
BranchNameKey fooBranch = BranchNameKey.create(project, "foo");
createBranch(fooBranch);
assertThat(codeOwnersPluginConfiguration.isDisabled(masterBranch)).isFalse();
assertThat(codeOwnersPluginConfiguration.isDisabled(fooBranch)).isFalse();
CodeOwnerProjectConfigInput input = new CodeOwnerProjectConfigInput();
input.disabledBranches = ImmutableList.of("refs/heads/master", "refs/heads/foo");
CodeOwnerProjectConfigInfo updatedConfig =
projectCodeOwnersApiFactory.project(project).updateConfig(input);
assertThat(updatedConfig.status.disabledBranches)
.containsExactly("refs/heads/master", "refs/heads/foo");
assertThat(codeOwnersPluginConfiguration.isDisabled(masterBranch)).isTrue();
assertThat(codeOwnersPluginConfiguration.isDisabled(fooBranch)).isTrue();
input = new CodeOwnerProjectConfigInput();
input.disabledBranches = ImmutableList.of();
updatedConfig = projectCodeOwnersApiFactory.project(project).updateConfig(input);
assertThat(updatedConfig.status.disabledBranches).isNull();
assertThat(codeOwnersPluginConfiguration.isDisabled(masterBranch)).isFalse();
assertThat(codeOwnersPluginConfiguration.isDisabled(fooBranch)).isFalse();
}
@Test
public void setDisabledBranchesRegEx() throws Exception {
BranchNameKey masterBranch = BranchNameKey.create(project, "master");
BranchNameKey fooBranch = BranchNameKey.create(project, "foo");
createBranch(fooBranch);
assertThat(codeOwnersPluginConfiguration.isDisabled(masterBranch)).isFalse();
assertThat(codeOwnersPluginConfiguration.isDisabled(fooBranch)).isFalse();
CodeOwnerProjectConfigInput input = new CodeOwnerProjectConfigInput();
input.disabledBranches = ImmutableList.of("refs/heads/*");
CodeOwnerProjectConfigInfo updatedConfig =
projectCodeOwnersApiFactory.project(project).updateConfig(input);
assertThat(updatedConfig.status.disabledBranches)
.containsExactly("refs/heads/master", "refs/heads/foo");
assertThat(codeOwnersPluginConfiguration.isDisabled(masterBranch)).isTrue();
assertThat(codeOwnersPluginConfiguration.isDisabled(fooBranch)).isTrue();
}
@Test
public void setDisabledBranchThatDoesntExist() throws Exception {
BranchNameKey fooBranch = BranchNameKey.create(project, "foo");
assertThat(codeOwnersPluginConfiguration.isDisabled(fooBranch)).isFalse();
CodeOwnerProjectConfigInput input = new CodeOwnerProjectConfigInput();
input.disabledBranches = ImmutableList.of("refs/heads/foo");
CodeOwnerProjectConfigInfo updatedConfig =
projectCodeOwnersApiFactory.project(project).updateConfig(input);
// status.disabledBranches does only contain existing branches
assertThat(updatedConfig.status.disabledBranches).isNull();
assertThat(codeOwnersPluginConfiguration.isDisabled(fooBranch)).isTrue();
createBranch(fooBranch);
assertThat(projectCodeOwnersApiFactory.project(project).getConfig().status.disabledBranches)
.containsExactly("refs/heads/foo");
}
@Test
public void cannotSetInvalidDisabledBranch() throws Exception {
CodeOwnerProjectConfigInput input = new CodeOwnerProjectConfigInput();
input.disabledBranches = ImmutableList.of("^refs/heads/[");
BadRequestException exception =
assertThrows(
BadRequestException.class,
() -> projectCodeOwnersApiFactory.project(project).updateConfig(input));
assertThat(exception)
.hasMessageThat()
.contains(
"invalid config:\n"
+ "* Disabled branch '^refs/heads/[' that is configured in code-owners.config"
+ " (parameter codeOwners.disabledBranch) is invalid: Unclosed character class");
}
@Test
public void setFileExtension() throws Exception {
assertThat(codeOwnersPluginConfiguration.getFileExtension(project)).isEmpty();
CodeOwnerProjectConfigInput input = new CodeOwnerProjectConfigInput();
input.fileExtension = "foo";
CodeOwnerProjectConfigInfo updatedConfig =
projectCodeOwnersApiFactory.project(project).updateConfig(input);
assertThat(updatedConfig.general.fileExtension).isEqualTo("foo");
assertThat(codeOwnersPluginConfiguration.getFileExtension(project)).value().isEqualTo("foo");
input.fileExtension = "";
updatedConfig = projectCodeOwnersApiFactory.project(project).updateConfig(input);
assertThat(updatedConfig.general.fileExtension).isNull();
assertThat(codeOwnersPluginConfiguration.getFileExtension(project)).isEmpty();
}
@Test
@UseClockStep
public void checkCommitData() throws Exception {
RevCommit head1 = projectOperations.project(project).getHead(RefNames.REFS_CONFIG);
CodeOwnerProjectConfigInput input = new CodeOwnerProjectConfigInput();
input.disabled = true;
projectCodeOwnersApiFactory.project(project).updateConfig(input);
// Check message, author and committer.
RevCommit head2 = projectOperations.project(project).getHead(RefNames.REFS_CONFIG);
assertThat(head2).isNotEqualTo(head1);
assertThat(head2.getFullMessage()).isEqualTo("Update code-owners configuration");
assertThat(head2.getAuthorIdent().getEmailAddress()).isEqualTo(admin.email());
assertThat(head2.getCommitterIdent().getName()).isEqualTo("Gerrit Code Review");
input.disabled = false;
projectCodeOwnersApiFactory.project(project).updateConfig(input);
// Check that timestamps differ for each commit.
RevCommit head3 = projectOperations.project(project).getHead(RefNames.REFS_CONFIG);
assertThat(head3).isNotEqualTo(head2);
assertThat(head3.getAuthorIdent().getWhen()).isGreaterThan(head2.getAuthorIdent().getWhen());
assertThat(head3.getCommitterIdent().getWhen())
.isGreaterThan(head2.getCommitterIdent().getWhen());
}
@Test
public void noOpUpdate() throws Exception {
RevCommit oldHead = projectOperations.project(project).getHead(RefNames.REFS_CONFIG);
projectCodeOwnersApiFactory.project(project).updateConfig(new CodeOwnerProjectConfigInput());
RevCommit newHead = projectOperations.project(project).getHead(RefNames.REFS_CONFIG);
assertThat(newHead).isEqualTo(oldHead);
}
@Test
public void updateConfigWhenRefsMetaConfigIsMissing() throws Exception {
ProjectState projectState = projectCache.get(project).orElseThrow(illegalState(project));
deleteRef.deleteSingleRef(projectState, RefNames.REFS_CONFIG);
assertThat(codeOwnersPluginConfiguration.isDisabled(project)).isFalse();
CodeOwnerProjectConfigInput input = new CodeOwnerProjectConfigInput();
input.disabled = true;
projectCodeOwnersApiFactory.project(project).updateConfig(input);
assertThat(codeOwnersPluginConfiguration.isDisabled(project)).isTrue();
}
}