LCOV - code coverage report
Current view: top level - acceptance/testsuite/project - TestProjectUpdate.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 90 90 100.0 %
Date: 2022-11-19 15:00:39 Functions: 46 46 100.0 %

          Line data    Source code
       1             : // Copyright (C) 2019 The Android Open Source Project
       2             : //
       3             : // Licensed under the Apache License, Version 2.0 (the "License");
       4             : // you may not use this file except in compliance with the License.
       5             : // You may obtain a copy of the License at
       6             : //
       7             : // http://www.apache.org/licenses/LICENSE-2.0
       8             : //
       9             : // Unless required by applicable law or agreed to in writing, software
      10             : // distributed under the License is distributed on an "AS IS" BASIS,
      11             : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             : // See the License for the specific language governing permissions and
      13             : // limitations under the License.
      14             : 
      15             : package com.google.gerrit.acceptance.testsuite.project;
      16             : 
      17             : import static com.google.common.base.Preconditions.checkArgument;
      18             : import static com.google.gerrit.entities.AccessSection.GLOBAL_CAPABILITIES;
      19             : import static java.util.Objects.requireNonNull;
      20             : 
      21             : import com.google.auto.value.AutoValue;
      22             : import com.google.common.collect.ImmutableList;
      23             : import com.google.common.collect.ImmutableMap;
      24             : import com.google.gerrit.acceptance.testsuite.ThrowingConsumer;
      25             : import com.google.gerrit.common.data.GlobalCapability;
      26             : import com.google.gerrit.entities.AccountGroup;
      27             : import com.google.gerrit.entities.LabelType;
      28             : import com.google.gerrit.entities.Permission;
      29             : import com.google.gerrit.entities.PermissionRange;
      30             : import com.google.gerrit.entities.PermissionRule;
      31             : import com.google.gerrit.entities.Project;
      32             : import com.google.gerrit.server.config.AllProjectsName;
      33             : import java.util.Optional;
      34             : import org.eclipse.jgit.lib.Constants;
      35             : 
      36             : @AutoValue
      37          81 : public abstract class TestProjectUpdate {
      38             :   /** Starts a builder for allowing a capability. */
      39             :   public static TestCapability.Builder allowCapability(String name) {
      40          22 :     return TestCapability.builder().name(name);
      41             :   }
      42             : 
      43             :   /** Records a global capability to be updated. */
      44             :   @AutoValue
      45          22 :   public abstract static class TestCapability {
      46             :     private static Builder builder() {
      47          22 :       return new AutoValue_TestProjectUpdate_TestCapability.Builder();
      48             :     }
      49             : 
      50             :     abstract String name();
      51             : 
      52             :     abstract AccountGroup.UUID group();
      53             : 
      54             :     abstract int min();
      55             : 
      56             :     abstract int max();
      57             : 
      58             :     /** Builder for {@link TestCapability}. */
      59             :     @AutoValue.Builder
      60          22 :     public abstract static class Builder {
      61             :       /** Sets the name of the capability. */
      62             :       public abstract Builder name(String name);
      63             : 
      64             :       abstract String name();
      65             : 
      66             :       /** Sets the group to which the capability applies. */
      67             :       public abstract Builder group(AccountGroup.UUID group);
      68             : 
      69             :       abstract Builder min(int min);
      70             : 
      71             :       abstract Optional<Integer> min();
      72             : 
      73             :       abstract Builder max(int max);
      74             : 
      75             :       abstract Optional<Integer> max();
      76             : 
      77             :       /** Sets the minimum and maximum values for the capability. */
      78             :       public Builder range(int min, int max) {
      79          22 :         checkNonInvertedRange(min, max);
      80          22 :         return min(min).max(max);
      81             :       }
      82             : 
      83             :       /** Builds the {@link TestCapability}. */
      84             :       abstract TestCapability autoBuild();
      85             : 
      86             :       public TestCapability build() {
      87          22 :         PermissionRange.WithDefaults withDefaults = GlobalCapability.getRange(name());
      88          22 :         if (withDefaults != null) {
      89           8 :           int min = min().orElse(withDefaults.getDefaultMin());
      90           8 :           int max = max().orElse(withDefaults.getDefaultMax());
      91           8 :           range(min, max);
      92             :           // Don't enforce range is nonempty; this is allowed for e.g. batchChangesLimit.
      93           8 :         } else {
      94          16 :           checkArgument(
      95          16 :               !min().isPresent() && !max().isPresent(),
      96             :               "capability %s does not support ranges",
      97          16 :               name());
      98          16 :           range(0, 0);
      99             :         }
     100             : 
     101          22 :         return autoBuild();
     102             :       }
     103             :     }
     104             :   }
     105             : 
     106             :   /** Starts a builder for allowing a permission. */
     107             :   public static TestPermission.Builder allow(String name) {
     108          55 :     return TestPermission.builder().name(name).action(PermissionRule.Action.ALLOW);
     109             :   }
     110             : 
     111             :   /** Starts a builder for denying a permission. */
     112             :   public static TestPermission.Builder deny(String name) {
     113           6 :     return TestPermission.builder().name(name).action(PermissionRule.Action.DENY);
     114             :   }
     115             : 
     116             :   /** Starts a builder for blocking a permission. */
     117             :   public static TestPermission.Builder block(String name) {
     118          47 :     return TestPermission.builder().name(name).action(PermissionRule.Action.BLOCK);
     119             :   }
     120             : 
     121             :   /**
     122             :    * Records a permission to be updated.
     123             :    *
     124             :    * <p>Not used for permissions that have ranges (label permissions) or global capabilities.
     125             :    */
     126             :   @AutoValue
     127          71 :   public abstract static class TestPermission {
     128             :     private static Builder builder() {
     129          71 :       return new AutoValue_TestProjectUpdate_TestPermission.Builder().force(false);
     130             :     }
     131             : 
     132             :     abstract String name();
     133             : 
     134             :     abstract String ref();
     135             : 
     136             :     abstract AccountGroup.UUID group();
     137             : 
     138             :     abstract PermissionRule.Action action();
     139             : 
     140             :     abstract boolean force();
     141             : 
     142             :     /** Builder for {@link TestPermission}. */
     143             :     @AutoValue.Builder
     144          71 :     public abstract static class Builder {
     145             :       abstract Builder name(String name);
     146             : 
     147             :       /** Sets the ref pattern used on the permission. */
     148             :       public abstract Builder ref(String ref);
     149             : 
     150             :       /** Sets the group to which the permission applies. */
     151             :       public abstract Builder group(AccountGroup.UUID groupUuid);
     152             : 
     153             :       abstract Builder action(PermissionRule.Action action);
     154             : 
     155             :       /** Sets whether the permission is a force permission. */
     156             :       public abstract Builder force(boolean force);
     157             : 
     158             :       /** Builds the {@link TestPermission}. */
     159             :       public abstract TestPermission build();
     160             :     }
     161             :   }
     162             : 
     163             :   /** Starts a builder for allowing a label permission. */
     164             :   public static TestLabelPermission.Builder allowLabel(String name) {
     165          32 :     return TestLabelPermission.builder().name(name).action(PermissionRule.Action.ALLOW);
     166             :   }
     167             : 
     168             :   /** Starts a builder for denying a label permission. */
     169             :   public static TestLabelPermission.Builder blockLabel(String name) {
     170           4 :     return TestLabelPermission.builder().name(name).action(PermissionRule.Action.BLOCK);
     171             :   }
     172             : 
     173             :   /** Records a label permission to be updated. */
     174             :   @AutoValue
     175          32 :   public abstract static class TestLabelPermission {
     176             :     private static Builder builder() {
     177          32 :       return new AutoValue_TestProjectUpdate_TestLabelPermission.Builder().impersonation(false);
     178             :     }
     179             : 
     180             :     abstract String name();
     181             : 
     182             :     abstract String ref();
     183             : 
     184             :     abstract AccountGroup.UUID group();
     185             : 
     186             :     abstract PermissionRule.Action action();
     187             : 
     188             :     abstract int min();
     189             : 
     190             :     abstract int max();
     191             : 
     192             :     abstract boolean impersonation();
     193             : 
     194             :     /** Builder for {@link TestLabelPermission}. */
     195             :     @AutoValue.Builder
     196          32 :     public abstract static class Builder {
     197             :       abstract Builder name(String name);
     198             : 
     199             :       /** Sets the ref pattern used on the permission. */
     200             :       public abstract Builder ref(String ref);
     201             : 
     202             :       /** Sets the group to which the permission applies. */
     203             :       public abstract Builder group(AccountGroup.UUID group);
     204             : 
     205             :       abstract Builder action(PermissionRule.Action action);
     206             : 
     207             :       abstract Builder min(int min);
     208             : 
     209             :       abstract Builder max(int max);
     210             : 
     211             :       /** Sets the minimum and maximum values for the permission. */
     212             :       public Builder range(int min, int max) {
     213          32 :         checkArgument(min != 0 || max != 0, "empty range");
     214          32 :         checkNonInvertedRange(min, max);
     215          32 :         return min(min).max(max);
     216             :       }
     217             : 
     218             :       /** Sets whether this permission should be for impersonating another user's votes. */
     219             :       public abstract Builder impersonation(boolean impersonation);
     220             : 
     221             :       abstract TestLabelPermission autoBuild();
     222             : 
     223             :       /** Builds the {@link TestPermission}. */
     224             :       public TestLabelPermission build() {
     225          32 :         TestLabelPermission result = autoBuild();
     226          32 :         checkLabelName(result.name());
     227          32 :         return result;
     228             :       }
     229             :     }
     230             :   }
     231             : 
     232             :   /**
     233             :    * Starts a builder for describing a permission key for deletion. Not for label permissions or
     234             :    * global capabilities.
     235             :    */
     236             :   public static TestPermissionKey.Builder permissionKey(String name) {
     237          13 :     return TestPermissionKey.builder().name(name);
     238             :   }
     239             : 
     240             :   /** Starts a builder for describing a label permission key for deletion. */
     241             :   public static TestPermissionKey.Builder labelPermissionKey(String name) {
     242           5 :     checkLabelName(name);
     243           5 :     return TestPermissionKey.builder().name(Permission.forLabel(name));
     244             :   }
     245             : 
     246             :   /** Starts a builder for describing a capability key for deletion. */
     247             :   public static TestPermissionKey.Builder capabilityKey(String name) {
     248           5 :     return TestPermissionKey.builder().name(name).section(GLOBAL_CAPABILITIES);
     249             :   }
     250             : 
     251             :   /** Records the key of a permission (of any type) for deletion. */
     252             :   @AutoValue
     253          19 :   public abstract static class TestPermissionKey {
     254             :     private static Builder builder() {
     255          19 :       return new AutoValue_TestProjectUpdate_TestPermissionKey.Builder();
     256             :     }
     257             : 
     258             :     abstract String section();
     259             : 
     260             :     abstract String name();
     261             : 
     262             :     abstract Optional<AccountGroup.UUID> group();
     263             : 
     264             :     @AutoValue.Builder
     265          19 :     public abstract static class Builder {
     266             :       abstract Builder section(String section);
     267             : 
     268             :       abstract Optional<String> section();
     269             : 
     270             :       /** Sets the ref pattern used on the permission. Not for global capabilities. */
     271             :       public Builder ref(String ref) {
     272          15 :         requireNonNull(ref);
     273          15 :         checkArgument(ref.startsWith(Constants.R_REFS), "must be a ref: %s", ref);
     274          15 :         checkArgument(
     275          15 :             !section().isPresent() || !section().get().equals(GLOBAL_CAPABILITIES),
     276             :             "can't set ref on global capability");
     277          15 :         return section(ref);
     278             :       }
     279             : 
     280             :       abstract Builder name(String name);
     281             : 
     282             :       /** Sets the group to which the permission applies. */
     283             :       public abstract Builder group(AccountGroup.UUID group);
     284             : 
     285             :       /** Builds the {@link TestPermissionKey}. */
     286             :       public abstract TestPermissionKey build();
     287             :     }
     288             :   }
     289             : 
     290             :   static Builder builder(
     291             :       Project.NameKey nameKey,
     292             :       AllProjectsName allProjectsName,
     293             :       ThrowingConsumer<TestProjectUpdate> projectUpdater) {
     294          81 :     return new AutoValue_TestProjectUpdate.Builder()
     295          81 :         .nameKey(nameKey)
     296          81 :         .allProjectsName(allProjectsName)
     297          81 :         .projectUpdater(projectUpdater)
     298          81 :         .removeAllAccessSections(false);
     299             :   }
     300             : 
     301             :   /** Builder for {@link TestProjectUpdate}. */
     302             :   @AutoValue.Builder
     303          81 :   public abstract static class Builder {
     304             :     abstract Builder nameKey(Project.NameKey project);
     305             : 
     306             :     abstract Builder allProjectsName(AllProjectsName allProjects);
     307             : 
     308             :     abstract ImmutableList.Builder<TestPermission> addedPermissionsBuilder();
     309             : 
     310             :     abstract ImmutableList.Builder<TestLabelPermission> addedLabelPermissionsBuilder();
     311             : 
     312             :     abstract ImmutableList.Builder<TestCapability> addedCapabilitiesBuilder();
     313             : 
     314             :     abstract ImmutableList.Builder<TestPermissionKey> removedPermissionsBuilder();
     315             : 
     316             :     abstract ImmutableMap.Builder<TestPermissionKey, Boolean> exclusiveGroupPermissionsBuilder();
     317             : 
     318             :     abstract Builder removeAllAccessSections(boolean value);
     319             : 
     320             :     /**
     321             :      * Removes all access sections. Useful when testing against a specific set of access sections or
     322             :      * permissions.
     323             :      */
     324             :     public Builder removeAllAccessSections() {
     325           2 :       return removeAllAccessSections(true);
     326             :     }
     327             : 
     328             :     /** Adds a permission to be included in this update. */
     329             :     public Builder add(TestPermission testPermission) {
     330          71 :       addedPermissionsBuilder().add(testPermission);
     331          71 :       return this;
     332             :     }
     333             : 
     334             :     /** Adds a permission to be included in this update. */
     335             :     public Builder add(TestPermission.Builder testPermissionBuilder) {
     336          71 :       return add(testPermissionBuilder.build());
     337             :     }
     338             : 
     339             :     /** Adds a label permission to be included in this update. */
     340             :     public Builder add(TestLabelPermission testLabelPermission) {
     341          32 :       addedLabelPermissionsBuilder().add(testLabelPermission);
     342          32 :       return this;
     343             :     }
     344             : 
     345             :     /** Adds a label permission to be included in this update. */
     346             :     public Builder add(TestLabelPermission.Builder testLabelPermissionBuilder) {
     347          31 :       return add(testLabelPermissionBuilder.build());
     348             :     }
     349             : 
     350             :     /** Adds a capability to be included in this update. */
     351             :     public Builder add(TestCapability testCapability) {
     352          22 :       addedCapabilitiesBuilder().add(testCapability);
     353          22 :       return this;
     354             :     }
     355             : 
     356             :     /** Adds a capability to be included in this update. */
     357             :     public Builder add(TestCapability.Builder testCapabilityBuilder) {
     358          22 :       return add(testCapabilityBuilder.build());
     359             :     }
     360             : 
     361             :     /** Removes a permission, label permission, or capability as part of this update. */
     362             :     public Builder remove(TestPermissionKey testPermissionKey) {
     363          17 :       removedPermissionsBuilder().add(testPermissionKey);
     364          17 :       return this;
     365             :     }
     366             : 
     367             :     /** Removes a permission, label permission, or capability as part of this update. */
     368             :     public Builder remove(TestPermissionKey.Builder testPermissionKeyBuilder) {
     369          15 :       return remove(testPermissionKeyBuilder.build());
     370             :     }
     371             : 
     372             :     /** Sets the exclusive bit bit for the given permission key. */
     373             :     public Builder setExclusiveGroup(
     374             :         TestPermissionKey.Builder testPermissionKeyBuilder, boolean exclusive) {
     375           4 :       return setExclusiveGroup(testPermissionKeyBuilder.build(), exclusive);
     376             :     }
     377             : 
     378             :     /** Sets the exclusive bit bit for the given permission key. */
     379             :     public Builder setExclusiveGroup(TestPermissionKey testPermissionKey, boolean exclusive) {
     380           4 :       checkArgument(
     381           4 :           !testPermissionKey.group().isPresent(),
     382             :           "do not specify group for setExclusiveGroup: %s",
     383             :           testPermissionKey);
     384           4 :       checkArgument(
     385           4 :           !testPermissionKey.section().equals(GLOBAL_CAPABILITIES),
     386             :           "setExclusiveGroup not valid for global capabilities: %s",
     387             :           testPermissionKey);
     388           4 :       exclusiveGroupPermissionsBuilder().put(testPermissionKey, exclusive);
     389           4 :       return this;
     390             :     }
     391             : 
     392             :     abstract Builder projectUpdater(ThrowingConsumer<TestProjectUpdate> projectUpdater);
     393             : 
     394             :     abstract TestProjectUpdate autoBuild();
     395             : 
     396             :     TestProjectUpdate build() {
     397          81 :       TestProjectUpdate projectUpdate = autoBuild();
     398          81 :       if (projectUpdate.hasCapabilityUpdates()) {
     399          22 :         checkArgument(
     400          22 :             projectUpdate.nameKey().equals(projectUpdate.allProjectsName()),
     401             :             "cannot update global capabilities on %s, only %s: %s",
     402          22 :             projectUpdate.nameKey(),
     403          22 :             projectUpdate.allProjectsName(),
     404             :             projectUpdate);
     405             :       }
     406          81 :       return projectUpdate;
     407             :     }
     408             : 
     409             :     /** Executes the update, updating the underlying project. */
     410             :     public void update() {
     411          81 :       TestProjectUpdate projectUpdate = build();
     412          81 :       projectUpdate.projectUpdater().acceptAndThrowSilently(projectUpdate);
     413          81 :     }
     414             :   }
     415             : 
     416             :   abstract Project.NameKey nameKey();
     417             : 
     418             :   abstract AllProjectsName allProjectsName();
     419             : 
     420             :   abstract ImmutableList<TestPermission> addedPermissions();
     421             : 
     422             :   abstract ImmutableList<TestLabelPermission> addedLabelPermissions();
     423             : 
     424             :   abstract ImmutableList<TestCapability> addedCapabilities();
     425             : 
     426             :   abstract ImmutableList<TestPermissionKey> removedPermissions();
     427             : 
     428             :   abstract ImmutableMap<TestPermissionKey, Boolean> exclusiveGroupPermissions();
     429             : 
     430             :   abstract ThrowingConsumer<TestProjectUpdate> projectUpdater();
     431             : 
     432             :   abstract boolean removeAllAccessSections();
     433             : 
     434             :   boolean hasCapabilityUpdates() {
     435          81 :     return !addedCapabilities().isEmpty()
     436          81 :         || removedPermissions().stream().anyMatch(k -> k.section().equals(GLOBAL_CAPABILITIES));
     437             :   }
     438             : 
     439             :   private static void checkLabelName(String name) {
     440             :     // "label-Code-Review" is technically a valid label name, and we don't prevent users from
     441             :     // using it in production, but specifying it in a test is programmer error.
     442          32 :     checkArgument(!Permission.isLabel(name), "expected label name, got permission name: %s", name);
     443          32 :     LabelType.checkName(name);
     444          32 :   }
     445             : 
     446             :   private static void checkNonInvertedRange(int min, int max) {
     447          39 :     checkArgument(min <= max, "inverted range: %s > %s", min, max);
     448          39 :   }
     449             : }

Generated by: LCOV version 1.16+git.20220603.dfeb750