| // 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.testsuite; |
| |
| import static java.util.Objects.requireNonNull; |
| |
| import com.google.auto.value.AutoValue; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableSet; |
| import com.google.gerrit.acceptance.testsuite.ThrowingFunction; |
| import com.google.gerrit.entities.BranchNameKey; |
| import com.google.gerrit.entities.Project; |
| import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfig; |
| import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfigReference; |
| import com.google.gerrit.plugins.codeowners.backend.CodeOwnerReference; |
| import com.google.gerrit.plugins.codeowners.backend.CodeOwnerSet; |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| import java.util.Optional; |
| |
| /** |
| * Test API to create a code owner config. |
| * |
| * <p>To execute the operations, no Gerrit permissions are necessary. |
| * |
| * <p><strong>Note:</strong> This interface is not implemented using the REST or extension API. |
| * Hence, it cannot be used for testing those APIs. |
| */ |
| @AutoValue |
| public abstract class TestCodeOwnerConfigCreation { |
| /** |
| * Gets the project in which the code owner config should be created. |
| * |
| * @return the project in which the code owner config should be created, {@link Optional#empty()} |
| * if the caller didn't specify a project for the code owner config creation |
| */ |
| public abstract Optional<Project.NameKey> project(); |
| |
| /** |
| * Gets the branch in which the code owner config should be created. |
| * |
| * @return the branch in which the code owner config should be created, {@link Optional#empty()} |
| * if the caller didn't specify a branch for the code owner config creation |
| */ |
| public abstract Optional<String> branch(); |
| |
| /** |
| * Gets the folder path in which the code owner config should be created. |
| * |
| * @return the folder path in which the code owner config should be created, {@link |
| * Optional#empty()} if the caller didn't specify a folder path for the code owner config |
| * creation |
| */ |
| public abstract Optional<Path> folderPath(); |
| |
| /** |
| * Gets the file name for the code owner config. |
| * |
| * @return the file name for the code owner config, {@link Optional#empty()} if the caller didn't |
| * specify a file name for the code owner config creation |
| */ |
| public abstract Optional<String> fileName(); |
| |
| /** |
| * Gets whether code owners from parent code owner configs (code owner configs in parent folders) |
| * should be ignored. |
| */ |
| public abstract boolean ignoreParentCodeOwners(); |
| |
| /** |
| * Gets the global code owners (without path expression) that should be set in the newly created |
| * code owner config. |
| * |
| * @return the global code owners that should be set in the newly created code owner config |
| */ |
| public abstract ImmutableSet<CodeOwnerReference> globalCodeOwners(); |
| |
| /** |
| * Gets the code owner sets that have been set for the new code owner config. |
| * |
| * <p>Doesn't include the code owner set for the global code owners that are defined by {@link |
| * #globalCodeOwners()}. Use {@link #computeCodeOwnerSets()} to get the code owner set for the |
| * global code owners included. |
| * |
| * @return the code owner sets that have been set for the new code owner config |
| */ |
| abstract ImmutableList<CodeOwnerSet> codeOwnerSets(); |
| |
| /** |
| * Gets the imports that have been set for the new code owner config. |
| * |
| * @return the imports that have been set for the new code owner config |
| */ |
| abstract ImmutableList<CodeOwnerConfigReference> imports(); |
| |
| /** |
| * Gets the code owner sets that should be set in the newly created code owner config. |
| * |
| * <p>Includes the global code owners that are defined by {@link #globalCodeOwners()}. |
| * |
| * @return the code owner sets that should be set in the newly created code owner config |
| */ |
| public ImmutableList<CodeOwnerSet> computeCodeOwnerSets() { |
| if (globalCodeOwners().isEmpty()) { |
| return codeOwnerSets(); |
| } |
| |
| return ImmutableList.<CodeOwnerSet>builder() |
| .add(CodeOwnerSet.createWithoutPathExpressions(globalCodeOwners())) |
| .addAll(codeOwnerSets()) |
| .build(); |
| } |
| |
| /** |
| * Returns the key for the code owner config that should be created. |
| * |
| * <p>If no project was specified, {@link IllegalStateException} is thrown. |
| * |
| * <p>If no branch was specified, {@code master} is used. |
| * |
| * <p>If no folder path was sepcified, {@code /} is used. |
| * |
| * @return the key for the code owner config that should be created |
| */ |
| public CodeOwnerConfig.Key key() { |
| Project.NameKey projectName = |
| project() |
| .orElseThrow( |
| () -> |
| new IllegalStateException( |
| "project not specified, specifying a project is required for code owner config creation")); |
| String branchName = branch().orElse("master"); |
| Path folderPath = folderPath().orElse(Paths.get("/")); |
| return CodeOwnerConfig.Key.create( |
| BranchNameKey.create(projectName, branchName), folderPath, fileName().orElse(null)); |
| } |
| |
| /** Returns whether the code owner config would be empty. */ |
| public boolean isEmpty() { |
| return !ignoreParentCodeOwners() && computeCodeOwnerSets().isEmpty() && imports().isEmpty(); |
| } |
| |
| /** |
| * Gets the function that creates the code owner config. |
| * |
| * @return the function that creates the code owner config |
| */ |
| abstract ThrowingFunction<TestCodeOwnerConfigCreation, CodeOwnerConfig.Key> |
| codeOwnerConfigCreator(); |
| |
| /** |
| * Creates a builder for a {@link TestCodeOwnerConfigCreation}. |
| * |
| * @param codeOwnerConfigCreator function that creates the code owner config |
| * @return builder for a {@link TestCodeOwnerConfigCreation} |
| */ |
| public static Builder builder( |
| ThrowingFunction<TestCodeOwnerConfigCreation, CodeOwnerConfig.Key> codeOwnerConfigCreator) { |
| return new AutoValue_TestCodeOwnerConfigCreation.Builder() |
| .ignoreParentCodeOwners(false) |
| .codeOwnerConfigCreator(codeOwnerConfigCreator); |
| } |
| |
| /** Builder for a {@link TestCodeOwnerConfigCreation}. */ |
| @AutoValue.Builder |
| public abstract static class Builder { |
| /** |
| * Sets the project in which the code owner config should be created. |
| * |
| * <p>Setting a project is mandatory. If a project is not set the creation of the code owner |
| * config will fail. |
| * |
| * @param project the project in which the code owner config should be created |
| * @return the Builder instance for chaining calls |
| */ |
| public abstract Builder project(Project.NameKey project); |
| |
| /** |
| * Sets the branch in which the code owner config should be created. |
| * |
| * <p>Setting a branch is optional. If a branch is not set {@code master} is used as default. |
| * |
| * @param branch the branch in which the code owner config should be created |
| * @return the Builder instance for chaining calls |
| */ |
| public abstract Builder branch(String branch); |
| |
| /** |
| * Sets the folder path in which the code owner config should be created. |
| * |
| * <p>Setting a folder path is optional. If a folder path is not set {@code /} is used as |
| * default. |
| * |
| * @param folderPath the folder path in which the code owner config should be created |
| * @return the Builder instance for chaining calls |
| */ |
| public abstract Builder folderPath(Path folderPath); |
| |
| /** |
| * Sets the folder path in which the code owner config should be created. |
| * |
| * @param folderPath the folder path in which the code owner config should be created |
| * @return the Builder instance for chaining calls |
| */ |
| public Builder folderPath(String folderPath) { |
| return folderPath(Paths.get(folderPath)); |
| } |
| |
| /** |
| * Sets the file name for the code owner config. |
| * |
| * @param fileName the file name for the code owner config |
| * @return the Builder instance for chaining calls |
| */ |
| public abstract Builder fileName(String fileName); |
| |
| /** |
| * Sets whether code owners from parent code owner configs (code owner configs in parent |
| * folders) should be ignored. |
| * |
| * @param ignoreParentCodeOwners whether code owners from parent code owner configs should be |
| * ignored |
| * @return the Builder instance for chaining calls |
| */ |
| public abstract Builder ignoreParentCodeOwners(boolean ignoreParentCodeOwners); |
| |
| /** |
| * Sets that code owners from parent code owner configs (code owner configs in parent folders) |
| * should be ignored. |
| * |
| * @return the Builder instance for chaining calls |
| */ |
| public Builder ignoreParentCodeOwners() { |
| return ignoreParentCodeOwners(true); |
| } |
| |
| /** |
| * Gets a builder to add global code owners |
| * |
| * @return builder to add global code owners |
| */ |
| abstract ImmutableSet.Builder<CodeOwnerReference> globalCodeOwnersBuilder(); |
| |
| /** |
| * Adds a global code owner for the given email. |
| * |
| * @param codeOwnerEmail email of the code owner |
| * @return the Builder instance for chaining calls |
| */ |
| public Builder addCodeOwnerEmail(String codeOwnerEmail) { |
| return addCodeOwner( |
| CodeOwnerReference.create(requireNonNull(codeOwnerEmail, "codeOwnerEmail"))); |
| } |
| |
| /** |
| * Adds a global code owner. |
| * |
| * @param codeOwnerReference reference to the code owner |
| * @return the Builder instance for chaining calls |
| */ |
| Builder addCodeOwner(CodeOwnerReference codeOwnerReference) { |
| globalCodeOwnersBuilder().add(requireNonNull(codeOwnerReference, "codeOwnerReference")); |
| return this; |
| } |
| |
| /** |
| * Gets a builder to add code owner sets. |
| * |
| * @return builder to add code owner sets |
| */ |
| abstract ImmutableList.Builder<CodeOwnerSet> codeOwnerSetsBuilder(); |
| |
| /** |
| * Adds a code owner set. |
| * |
| * @param codeOwnerSet code owner set that should be added |
| * @return the Builder instance for chaining calls |
| */ |
| public Builder addCodeOwnerSet(CodeOwnerSet codeOwnerSet) { |
| codeOwnerSetsBuilder().add(requireNonNull(codeOwnerSet, "codeOwnerSet")); |
| return this; |
| } |
| |
| /** |
| * Gets a builder to add imports. |
| * |
| * @return builder to add imports |
| */ |
| abstract ImmutableList.Builder<CodeOwnerConfigReference> importsBuilder(); |
| |
| /** |
| * Adds an import. |
| * |
| * @param codeOwnerConfigReference reference to the code owner config that should be imported |
| * @return the Builder instance for chaining calls |
| */ |
| public Builder addImport(CodeOwnerConfigReference codeOwnerConfigReference) { |
| importsBuilder().add(requireNonNull(codeOwnerConfigReference, "codeOwnerConfigReference")); |
| return this; |
| } |
| |
| /** |
| * Sets the function that creates the code owner config. |
| * |
| * @param codeOwnerConfigCreator the function that creates the code owner config |
| * @return the Builder instance for chaining calls |
| */ |
| abstract Builder codeOwnerConfigCreator( |
| ThrowingFunction<TestCodeOwnerConfigCreation, CodeOwnerConfig.Key> codeOwnerConfigCreator); |
| |
| /** |
| * Builds the {@link TestCodeOwnerConfigCreation} instance. |
| * |
| * @return the {@link TestCodeOwnerConfigCreation} instance |
| */ |
| abstract TestCodeOwnerConfigCreation autoBuild(); |
| |
| /** |
| * Executes the code owner config creation as specified. |
| * |
| * @return the key of the code owner config |
| */ |
| public CodeOwnerConfig.Key create() { |
| TestCodeOwnerConfigCreation creation = autoBuild(); |
| return creation.codeOwnerConfigCreator().applyAndThrowSilently(creation); |
| } |
| } |
| } |