| // Copyright (C) 2020 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.testing.GerritJUnit.assertThrows; |
| |
| import com.google.gerrit.acceptance.TestAccount; |
| import com.google.gerrit.entities.RefNames; |
| import com.google.gerrit.extensions.restapi.BadRequestException; |
| import com.google.gerrit.plugins.codeowners.acceptance.AbstractCodeOwnersIT; |
| import com.google.gerrit.plugins.codeowners.backend.CodeOwnerBackend; |
| import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfig; |
| import com.google.gerrit.plugins.codeowners.backend.CodeOwnerSet; |
| import com.google.gerrit.plugins.codeowners.backend.config.BackendConfig; |
| import com.google.gerrit.plugins.codeowners.backend.findowners.FindOwnersBackend; |
| import com.google.gerrit.plugins.codeowners.backend.proto.ProtoBackend; |
| import com.google.gerrit.plugins.codeowners.util.JgitPath; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| /** |
| * Acceptance test for the {@link |
| * com.google.gerrit.plugins.codeowners.restapi.GetCodeOwnerConfigFiles} REST endpoint. |
| */ |
| public class GetCodeOwnerConfigFilesIT extends AbstractCodeOwnersIT { |
| private BackendConfig backendConfig; |
| |
| @Before |
| public void setUpCodeOwnersPlugin() throws Exception { |
| backendConfig = plugin.getSysInjector().getInstance(BackendConfig.class); |
| } |
| |
| @Test |
| public void noCodeOwnerConfigFiles() throws Exception { |
| assertThat( |
| projectCodeOwnersApiFactory |
| .project(project) |
| .branch("master") |
| .codeOwnerConfigFiles() |
| .paths()) |
| .isEmpty(); |
| } |
| |
| @Test |
| public void defaultCodeOwnerConfigFileIsSkipped() throws Exception { |
| codeOwnerConfigOperations |
| .newCodeOwnerConfig() |
| .project(project) |
| .branch(RefNames.REFS_CONFIG) |
| .folderPath("/") |
| .addCodeOwnerEmail(user.email()) |
| .create(); |
| |
| assertThat( |
| projectCodeOwnersApiFactory |
| .project(project) |
| .branch("master") |
| .codeOwnerConfigFiles() |
| .paths()) |
| .isEmpty(); |
| } |
| |
| @Test |
| public void getCodeOwnerConfigFiles() throws Exception { |
| CodeOwnerConfig.Key codeOwnerConfigKey1 = |
| codeOwnerConfigOperations |
| .newCodeOwnerConfig() |
| .project(project) |
| .branch("master") |
| .folderPath("/") |
| .addCodeOwnerEmail(user.email()) |
| .create(); |
| |
| CodeOwnerConfig.Key codeOwnerConfigKey2 = |
| codeOwnerConfigOperations |
| .newCodeOwnerConfig() |
| .project(project) |
| .branch("master") |
| .folderPath("/foo/") |
| .addCodeOwnerEmail(admin.email()) |
| .create(); |
| |
| CodeOwnerConfig.Key codeOwnerConfigKey3 = |
| codeOwnerConfigOperations |
| .newCodeOwnerConfig() |
| .project(project) |
| .branch("master") |
| .folderPath("/foo/bar/") |
| .addCodeOwnerEmail(user.email()) |
| .create(); |
| |
| assertThat( |
| projectCodeOwnersApiFactory |
| .project(project) |
| .branch("master") |
| .codeOwnerConfigFiles() |
| .paths()) |
| .containsExactly( |
| codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey1).getFilePath(), |
| codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey2).getFilePath(), |
| codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey3).getFilePath()) |
| .inOrder(); |
| } |
| |
| @Test |
| public void getCodeOwnerConfigFilesWithPrefixes() throws Exception { |
| CodeOwnerConfig.Key codeOwnerConfigKey1 = |
| codeOwnerConfigOperations |
| .newCodeOwnerConfig() |
| .project(project) |
| .branch("master") |
| .fileName("prefix_" + getCodeOwnerConfigFileName()) |
| .folderPath("/") |
| .addCodeOwnerEmail(user.email()) |
| .create(); |
| |
| CodeOwnerConfig.Key codeOwnerConfigKey2 = |
| codeOwnerConfigOperations |
| .newCodeOwnerConfig() |
| .project(project) |
| .branch("master") |
| .folderPath("/foo/") |
| .fileName("prefix_" + getCodeOwnerConfigFileName()) |
| .addCodeOwnerEmail(admin.email()) |
| .create(); |
| |
| assertThat( |
| projectCodeOwnersApiFactory |
| .project(project) |
| .branch("master") |
| .codeOwnerConfigFiles() |
| .paths()) |
| .containsExactly( |
| codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey2).getFilePath(), |
| codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey1).getFilePath()) |
| .inOrder(); |
| } |
| |
| @Test |
| public void getCodeOwnerConfigFilesWithExtensions() throws Exception { |
| CodeOwnerConfig.Key codeOwnerConfigKey1 = |
| codeOwnerConfigOperations |
| .newCodeOwnerConfig() |
| .project(project) |
| .branch("master") |
| .fileName(getCodeOwnerConfigFileName() + "_extension") |
| .folderPath("/") |
| .addCodeOwnerEmail(user.email()) |
| .create(); |
| |
| CodeOwnerConfig.Key codeOwnerConfigKey2 = |
| codeOwnerConfigOperations |
| .newCodeOwnerConfig() |
| .project(project) |
| .branch("master") |
| .folderPath("/foo/") |
| .fileName(getCodeOwnerConfigFileName() + "_extension") |
| .addCodeOwnerEmail(admin.email()) |
| .create(); |
| |
| assertThat( |
| projectCodeOwnersApiFactory |
| .project(project) |
| .branch("master") |
| .codeOwnerConfigFiles() |
| .paths()) |
| .containsExactly( |
| codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey1).getFilePath(), |
| codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey2).getFilePath()) |
| .inOrder(); |
| } |
| |
| @Test |
| public void nonCodeOwnerConfigFilesAreNotReturned() throws Exception { |
| // create a code owner config file with a name that is not recognized as code owner config file |
| codeOwnerConfigOperations |
| .newCodeOwnerConfig() |
| .project(project) |
| .branch("master") |
| .folderPath("/foo/") |
| .fileName("non-code-owner-config") |
| .addCodeOwnerEmail(admin.email()) |
| .create(); |
| |
| assertThat( |
| projectCodeOwnersApiFactory |
| .project(project) |
| .branch("master") |
| .codeOwnerConfigFiles() |
| .paths()) |
| .isEmpty(); |
| } |
| |
| @Test |
| public void getCodeOwnerConfigFilesIfInvalidCodeOwnerConfigFilesExist() throws Exception { |
| createNonParseableCodeOwnerConfig(getCodeOwnerConfigFileName()); |
| |
| CodeOwnerConfig.Key codeOwnerConfigKey = |
| codeOwnerConfigOperations |
| .newCodeOwnerConfig() |
| .project(project) |
| .branch("master") |
| .folderPath("/foo/") |
| .addCodeOwnerEmail(admin.email()) |
| .create(); |
| |
| assertThat( |
| projectCodeOwnersApiFactory |
| .project(project) |
| .branch("master") |
| .codeOwnerConfigFiles() |
| .paths()) |
| .containsExactly( |
| codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).getFilePath()); |
| } |
| |
| @Test |
| public void includeInvalidCodeOwnerConfigFiles() throws Exception { |
| String nameOfInvalidCodeOwnerConfigFile = getCodeOwnerConfigFileName(); |
| createNonParseableCodeOwnerConfig(nameOfInvalidCodeOwnerConfigFile); |
| |
| CodeOwnerConfig.Key codeOwnerConfigKey = |
| codeOwnerConfigOperations |
| .newCodeOwnerConfig() |
| .project(project) |
| .branch("master") |
| .folderPath("/foo/") |
| .addCodeOwnerEmail(admin.email()) |
| .create(); |
| |
| assertThat( |
| projectCodeOwnersApiFactory |
| .project(project) |
| .branch("master") |
| .codeOwnerConfigFiles() |
| .includeNonParsableFiles(true) |
| .paths()) |
| .containsExactly( |
| JgitPath.of(nameOfInvalidCodeOwnerConfigFile).getAsAbsolutePath().toString(), |
| codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey).getFilePath()); |
| } |
| |
| @Test |
| public void includeNonParsableFilesAndEmailOptionsAreMutuallyExclusive() throws Exception { |
| BadRequestException exception = |
| assertThrows( |
| BadRequestException.class, |
| () -> |
| projectCodeOwnersApiFactory |
| .project(project) |
| .branch("master") |
| .codeOwnerConfigFiles() |
| .includeNonParsableFiles(true) |
| .withEmail(admin.email()) |
| .paths()); |
| assertThat(exception) |
| .hasMessageThat() |
| .isEqualTo("the options 'email' and 'include-non-parsable-files' are mutually exclusive"); |
| } |
| |
| @Test |
| public void filterByEmail() throws Exception { |
| TestAccount user2 = accountCreator.user2(); |
| TestAccount user3 = accountCreator.create("user3", "user3@example.com", "User3", null); |
| |
| CodeOwnerConfig.Key codeOwnerConfigKey1 = |
| codeOwnerConfigOperations |
| .newCodeOwnerConfig() |
| .project(project) |
| .branch("master") |
| .folderPath("/") |
| .addCodeOwnerEmail(user.email()) |
| .create(); |
| |
| CodeOwnerConfig.Key codeOwnerConfigKey2 = |
| codeOwnerConfigOperations |
| .newCodeOwnerConfig() |
| .project(project) |
| .branch("master") |
| .folderPath("/foo/") |
| .addCodeOwnerEmail(admin.email()) |
| .create(); |
| |
| CodeOwnerConfig.Key codeOwnerConfigKey3 = |
| codeOwnerConfigOperations |
| .newCodeOwnerConfig() |
| .project(project) |
| .branch("master") |
| .folderPath("/foo/bar/") |
| .addCodeOwnerSet( |
| CodeOwnerSet.builder() |
| .addPathExpression("foo") |
| .addCodeOwnerEmail(user.email()) |
| .build()) |
| .create(); |
| |
| CodeOwnerConfig.Key codeOwnerConfigKey4 = |
| codeOwnerConfigOperations |
| .newCodeOwnerConfig() |
| .project(project) |
| .branch("master") |
| .folderPath("/foo/baz/") |
| .addCodeOwnerEmail(admin.email()) |
| .addCodeOwnerEmail(user.email()) |
| .create(); |
| |
| CodeOwnerConfig.Key codeOwnerConfigKey5 = |
| codeOwnerConfigOperations |
| .newCodeOwnerConfig() |
| .project(project) |
| .branch("master") |
| .folderPath("/foo/xyz/") |
| .addCodeOwnerEmail(admin.email()) |
| .addCodeOwnerEmail(user2.email()) |
| .create(); |
| |
| assertThat( |
| projectCodeOwnersApiFactory |
| .project(project) |
| .branch("master") |
| .codeOwnerConfigFiles() |
| .withEmail(admin.email()) |
| .paths()) |
| .containsExactly( |
| codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey2).getFilePath(), |
| codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey4).getFilePath(), |
| codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey5).getFilePath()) |
| .inOrder(); |
| |
| assertThat( |
| projectCodeOwnersApiFactory |
| .project(project) |
| .branch("master") |
| .codeOwnerConfigFiles() |
| .withEmail(user.email()) |
| .paths()) |
| .containsExactly( |
| codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey1).getFilePath(), |
| codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey3).getFilePath(), |
| codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey4).getFilePath()) |
| .inOrder(); |
| |
| assertThat( |
| projectCodeOwnersApiFactory |
| .project(project) |
| .branch("master") |
| .codeOwnerConfigFiles() |
| .withEmail(user2.email()) |
| .paths()) |
| .containsExactly( |
| codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey5).getFilePath()); |
| |
| assertThat( |
| projectCodeOwnersApiFactory |
| .project(project) |
| .branch("master") |
| .codeOwnerConfigFiles() |
| .withEmail(user3.email()) |
| .paths()) |
| .isEmpty(); |
| } |
| |
| @Test |
| public void getCodeOwnerConfigFilesWithPathGlob() throws Exception { |
| codeOwnerConfigOperations |
| .newCodeOwnerConfig() |
| .project(project) |
| .branch("master") |
| .folderPath("/") |
| .addCodeOwnerEmail(user.email()) |
| .create(); |
| |
| CodeOwnerConfig.Key codeOwnerConfigKey2 = |
| codeOwnerConfigOperations |
| .newCodeOwnerConfig() |
| .project(project) |
| .branch("master") |
| .folderPath("/foo/") |
| .addCodeOwnerEmail(admin.email()) |
| .create(); |
| |
| CodeOwnerConfig.Key codeOwnerConfigKey3 = |
| codeOwnerConfigOperations |
| .newCodeOwnerConfig() |
| .project(project) |
| .branch("master") |
| .folderPath("/foo/bar/") |
| .addCodeOwnerEmail(user.email()) |
| .create(); |
| |
| assertThat( |
| projectCodeOwnersApiFactory |
| .project(project) |
| .branch("master") |
| .codeOwnerConfigFiles() |
| .withPath("/foo/bar/" + getCodeOwnerConfigFileName()) |
| .paths()) |
| .containsExactly( |
| codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey3).getFilePath()); |
| |
| assertThat( |
| projectCodeOwnersApiFactory |
| .project(project) |
| .branch("master") |
| .codeOwnerConfigFiles() |
| .withPath("/foo/bar/*") |
| .paths()) |
| .containsExactly( |
| codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey3).getFilePath()) |
| .inOrder(); |
| |
| assertThat( |
| projectCodeOwnersApiFactory |
| .project(project) |
| .branch("master") |
| .codeOwnerConfigFiles() |
| .withPath("/foo/**") |
| .paths()) |
| .containsExactly( |
| codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey2).getFilePath(), |
| codeOwnerConfigOperations.codeOwnerConfig(codeOwnerConfigKey3).getFilePath()) |
| .inOrder(); |
| } |
| |
| private String getCodeOwnerConfigFileName() { |
| CodeOwnerBackend backend = backendConfig.getDefaultBackend(); |
| if (backend instanceof FindOwnersBackend) { |
| return FindOwnersBackend.CODE_OWNER_CONFIG_FILE_NAME; |
| } else if (backend instanceof ProtoBackend) { |
| return ProtoBackend.CODE_OWNER_CONFIG_FILE_NAME; |
| } |
| throw new IllegalStateException("unknown code owner backend: " + backend.getClass().getName()); |
| } |
| } |