Merge changes from topic "test-project-update-1"
* changes:
TestProjectUpdate: Support granting global capabilities
TestProjectUpdate: Support setting label permissions
AbstractDaemonTest: Use ProjectOperations for block/deny/grant
Introduce TestProjectUpdate to update project config
Add ConfigSubject over JGit Configs
ProjectOperations: Add methods for reading (Project)Config
AbstractDaemonTest: Temporarily make projectOperations protected
diff --git a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
index 07c80f5..2fd515f 100644
--- a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
+++ b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
@@ -38,11 +38,13 @@
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
+import com.google.common.collect.Streams;
import com.google.common.jimfs.Jimfs;
import com.google.common.primitives.Chars;
import com.google.gerrit.acceptance.AcceptanceTestRequestScope.Context;
import com.google.gerrit.acceptance.testsuite.account.TestSshKeys;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
+import com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.data.AccessSection;
@@ -52,7 +54,6 @@
import com.google.gerrit.common.data.LabelType;
import com.google.gerrit.common.data.LabelValue;
import com.google.gerrit.common.data.Permission;
-import com.google.gerrit.common.data.PermissionRange;
import com.google.gerrit.common.data.PermissionRule;
import com.google.gerrit.common.data.PermissionRule.Action;
import com.google.gerrit.extensions.api.GerritApi;
@@ -277,6 +278,9 @@
protected boolean testRequiresSsh;
protected BlockStrategy noSleepBlockStrategy = t -> {}; // Don't sleep in tests.
+ // TODO(dborowitz): Push down into callers that need it.
+ @Inject protected ProjectOperations projectOperations;
+
@Inject private AbstractChangeNotes.Args changeNotesArgs;
@Inject private AccountIndexCollection accountIndexes;
@Inject private AccountIndexer accountIndexer;
@@ -286,7 +290,6 @@
@Inject private PluginGuiceEnvironment pluginGuiceEnvironment;
@Inject private PluginUser.Factory pluginUserFactory;
@Inject private ProjectIndexCollection projectIndexes;
- @Inject private ProjectOperations projectOperations;
@Inject private RequestScopeOperations requestScopeOperations;
@Inject private SitePaths sitePaths;
@@ -884,23 +887,23 @@
allow(project, ref, permission, id);
}
- protected void allow(Project.NameKey p, String ref, String permission, AccountGroup.UUID id)
- throws Exception {
- try (ProjectConfigUpdate u = updateProject(p)) {
- Util.allow(u.getConfig(), permission, id, ref);
- u.save();
- }
+ protected void allow(Project.NameKey p, String ref, String permission, AccountGroup.UUID id) {
+ projectOperations
+ .project(p)
+ .forUpdate()
+ .add(TestProjectUpdate.allow(permission).ref(ref).group(id))
+ .update();
}
protected void allowGlobalCapabilities(
AccountGroup.UUID id, int min, int max, String... capabilityNames) throws Exception {
- try (ProjectConfigUpdate u = updateProject(allProjects)) {
- for (String capabilityName : capabilityNames) {
- Util.allow(
- u.getConfig(), capabilityName, id, new PermissionRange(capabilityName, min, max));
- }
- u.save();
- }
+ // TODO(dborowitz): When inlining:
+ // * add a variant that takes a single String
+ // * explicitly add multiple values in callers instead of looping
+ TestProjectUpdate.Builder b = projectOperations.project(allProjects).forUpdate();
+ Arrays.stream(capabilityNames)
+ .forEach(c -> b.add(TestProjectUpdate.allowCapability(c).group(id).range(min, max)));
+ b.update();
}
protected void allowGlobalCapabilities(AccountGroup.UUID id, String... capabilityNames)
@@ -910,12 +913,13 @@
protected void allowGlobalCapabilities(AccountGroup.UUID id, Iterable<String> capabilityNames)
throws Exception {
- try (ProjectConfigUpdate u = updateProject(allProjects)) {
- for (String capabilityName : capabilityNames) {
- Util.allow(u.getConfig(), capabilityName, id);
- }
- u.save();
- }
+ // TODO(dborowitz): When inlining:
+ // * add a variant that takes a single String
+ // * explicitly add multiple values in callers instead of looping
+ TestProjectUpdate.Builder b = projectOperations.project(allProjects).forUpdate();
+ Streams.stream(capabilityNames)
+ .forEach(c -> b.add(TestProjectUpdate.allowCapability(c).group(id)));
+ b.update();
}
protected void removeGlobalCapabilities(AccountGroup.UUID id, String... capabilityNames)
@@ -957,44 +961,52 @@
protected void deny(Project.NameKey p, String ref, String permission, AccountGroup.UUID id)
throws Exception {
- try (ProjectConfigUpdate u = updateProject(p)) {
- Util.deny(u.getConfig(), permission, id, ref);
- u.save();
- }
+ projectOperations
+ .project(p)
+ .forUpdate()
+ .add(TestProjectUpdate.deny(permission).ref(ref).group(id))
+ .update();
}
- protected PermissionRule block(String ref, String permission, AccountGroup.UUID id)
- throws Exception {
- return block(project, ref, permission, id);
+ protected void block(String ref, String permission, AccountGroup.UUID id) throws Exception {
+ block(project, ref, permission, id);
}
- protected PermissionRule block(
- Project.NameKey project, String ref, String permission, AccountGroup.UUID id)
+ protected void block(Project.NameKey project, String ref, String permission, AccountGroup.UUID id)
throws Exception {
- try (ProjectConfigUpdate u = updateProject(project)) {
- PermissionRule rule = Util.block(u.getConfig(), permission, id, ref);
- u.save();
- return rule;
- }
+ projectOperations
+ .project(project)
+ .forUpdate()
+ .add(TestProjectUpdate.block(permission).ref(ref).group(id))
+ .update();
}
protected void blockLabel(
String label, int min, int max, AccountGroup.UUID id, String ref, Project.NameKey project)
throws Exception {
- try (ProjectConfigUpdate u = updateProject(project)) {
- Util.block(u.getConfig(), Permission.LABEL + label, min, max, id, ref);
- u.save();
- }
+ projectOperations
+ .project(project)
+ .forUpdate()
+ .add(TestProjectUpdate.blockLabel(label).ref(ref).group(id).range(min, max))
+ .update();
}
protected void grant(Project.NameKey project, String ref, String permission)
throws RepositoryNotFoundException, IOException, ConfigInvalidException {
- grant(project, ref, permission, false);
+ projectOperations
+ .project(project)
+ .forUpdate()
+ .add(TestProjectUpdate.allow(permission).ref(ref).group(adminGroupUuid()))
+ .update();
}
protected void grant(Project.NameKey project, String ref, String permission, boolean force)
throws RepositoryNotFoundException, IOException, ConfigInvalidException {
- grant(project, ref, permission, force, adminGroupUuid());
+ projectOperations
+ .project(project)
+ .forUpdate()
+ .add(TestProjectUpdate.allow(permission).ref(ref).group(adminGroupUuid()).force(force))
+ .update();
}
protected void grant(
@@ -1004,17 +1016,11 @@
boolean force,
AccountGroup.UUID groupUUID)
throws RepositoryNotFoundException, IOException, ConfigInvalidException {
- try (MetaDataUpdate md = metaDataUpdateFactory.create(project)) {
- md.setMessage(String.format("Grant %s on %s", permission, ref));
- ProjectConfig config = projectConfigFactory.read(md);
- AccessSection s = config.getAccessSection(ref, true);
- Permission p = s.getPermission(permission, true);
- PermissionRule rule = Util.newRule(config, groupUUID);
- rule.setForce(force);
- p.add(rule);
- config.commit(md);
- projectCache.evict(config.getProject());
- }
+ projectOperations
+ .project(project)
+ .forUpdate()
+ .add(TestProjectUpdate.allow(permission).ref(ref).group(groupUUID).force(force))
+ .update();
}
protected void grantLabel(
@@ -1023,25 +1029,19 @@
int max,
Project.NameKey project,
String ref,
- boolean force,
AccountGroup.UUID groupUUID,
boolean exclusive)
throws RepositoryNotFoundException, IOException, ConfigInvalidException {
- String permission = Permission.LABEL + label;
- try (MetaDataUpdate md = metaDataUpdateFactory.create(project)) {
- md.setMessage(String.format("Grant %s on %s", permission, ref));
- ProjectConfig config = projectConfigFactory.read(md);
- AccessSection s = config.getAccessSection(ref, true);
- Permission p = s.getPermission(permission, true);
- p.setExclusiveGroup(exclusive);
- PermissionRule rule = Util.newRule(config, groupUUID);
- rule.setForce(force);
- rule.setMin(min);
- rule.setMax(max);
- p.add(rule);
- config.commit(md);
- projectCache.evict(config.getProject());
- }
+ projectOperations
+ .project(project)
+ .forUpdate()
+ .add(
+ TestProjectUpdate.allowLabel(label)
+ .ref(ref)
+ .group(groupUUID)
+ .range(min, max)
+ .exclusive(exclusive))
+ .update();
}
protected void removePermission(Project.NameKey project, String ref, String permission)
diff --git a/java/com/google/gerrit/acceptance/BUILD b/java/com/google/gerrit/acceptance/BUILD
index 0714d22..ada2fb6 100644
--- a/java/com/google/gerrit/acceptance/BUILD
+++ b/java/com/google/gerrit/acceptance/BUILD
@@ -35,6 +35,7 @@
"//java/com/google/gerrit/server/restapi",
"//java/com/google/gerrit/sshd",
"//java/com/google/gerrit/testing:gerrit-test-util",
+ "//java/com/google/gerrit/truth",
"//lib:args4j",
"//lib:gson",
"//lib:guava-retrying",
diff --git a/java/com/google/gerrit/acceptance/testsuite/project/ProjectOperations.java b/java/com/google/gerrit/acceptance/testsuite/project/ProjectOperations.java
index 029d161..fc4caf8 100644
--- a/java/com/google/gerrit/acceptance/testsuite/project/ProjectOperations.java
+++ b/java/com/google/gerrit/acceptance/testsuite/project/ProjectOperations.java
@@ -15,6 +15,8 @@
package com.google.gerrit.acceptance.testsuite.project;
import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.server.project.ProjectConfig;
+import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.revwalk.RevCommit;
/**
@@ -40,5 +42,33 @@
* fully qualified refname ("refs/heads/master").
*/
boolean hasHead(String branchName);
+
+ /** Returns a fresh {@link ProjectConfig} read from the tip of {@code refs/meta/config}. */
+ ProjectConfig getProjectConfig();
+
+ /**
+ * Returns a fresh JGit {@link Config} instance read from {@code project.config} at the tip of
+ * {@code refs/meta/config}. Does not have a base config, i.e. does not respect {@code
+ * $site_path/etc/project.config}.
+ */
+ Config getConfig();
+
+ /**
+ * Starts the fluent chain to update a project. The returned builder can be used to specify how
+ * the attributes of the project should be modified. To update the project for real, the {@link
+ * TestProjectUpdate.Builder#update()} must be called.
+ *
+ * <p>Example:
+ *
+ * <pre>
+ * projectOperations
+ * .forUpdate()
+ * .add(allow(ABANDON).ref("refs/*").group(REGISTERED_USERS))
+ * .update();
+ * </pre>
+ *
+ * @return a builder to update the check.
+ */
+ TestProjectUpdate.Builder forUpdate();
}
}
diff --git a/java/com/google/gerrit/acceptance/testsuite/project/ProjectOperationsImpl.java b/java/com/google/gerrit/acceptance/testsuite/project/ProjectOperationsImpl.java
index 4180aaa..6835ae4 100644
--- a/java/com/google/gerrit/acceptance/testsuite/project/ProjectOperationsImpl.java
+++ b/java/com/google/gerrit/acceptance/testsuite/project/ProjectOperationsImpl.java
@@ -14,31 +14,62 @@
package com.google.gerrit.acceptance.testsuite.project;
+import static com.google.gerrit.reviewdb.client.RefNames.REFS_CONFIG;
+import static com.google.gerrit.server.project.ProjectConfig.PROJECT_CONFIG;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Objects.requireNonNull;
+import com.google.common.collect.ImmutableList;
import com.google.gerrit.acceptance.testsuite.project.TestProjectCreation.Builder;
+import com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.TestCapability;
+import com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.TestLabelPermission;
+import com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.TestPermission;
+import com.google.gerrit.common.data.AccessSection;
+import com.google.gerrit.common.data.Permission;
+import com.google.gerrit.common.data.PermissionRule;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.project.CreateProjectArgs;
+import com.google.gerrit.server.project.ProjectCache;
+import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.project.ProjectCreator;
+import com.google.gerrit.server.project.testing.Util;
import com.google.inject.Inject;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import org.apache.commons.lang.RandomStringUtils;
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.treewalk.TreeWalk;
public class ProjectOperationsImpl implements ProjectOperations {
- private final ProjectCreator projectCreator;
private final GitRepositoryManager repoManager;
+ private final MetaDataUpdate.Server metaDataUpdateFactory;
+ private final ProjectCache projectCache;
+ private final ProjectConfig.Factory projectConfigFactory;
+ private final ProjectCreator projectCreator;
@Inject
- ProjectOperationsImpl(GitRepositoryManager repoManager, ProjectCreator projectCreator) {
+ ProjectOperationsImpl(
+ GitRepositoryManager repoManager,
+ MetaDataUpdate.Server metaDataUpdateFactory,
+ ProjectCache projectCache,
+ ProjectConfig.Factory projectConfigFactory,
+ ProjectCreator projectCreator) {
this.repoManager = repoManager;
+ this.metaDataUpdateFactory = metaDataUpdateFactory;
+ this.projectCache = projectCache;
+ this.projectConfigFactory = projectConfigFactory;
this.projectCreator = projectCreator;
}
@@ -68,7 +99,6 @@
}
private class PerProjectOperations implements ProjectOperations.PerProjectOperations {
-
Project.NameKey nameKey;
PerProjectOperations(Project.NameKey nameKey) {
@@ -85,6 +115,60 @@
return headOrNull(branch) != null;
}
+ @Override
+ public TestProjectUpdate.Builder forUpdate() {
+ return TestProjectUpdate.builder(this::updateProject);
+ }
+
+ private void updateProject(TestProjectUpdate projectUpdate)
+ throws IOException, ConfigInvalidException {
+ try (MetaDataUpdate metaDataUpdate = metaDataUpdateFactory.create(nameKey)) {
+ ProjectConfig projectConfig = projectConfigFactory.read(metaDataUpdate);
+ addCapabilities(projectConfig, projectUpdate.addedCapabilities());
+ addPermissions(projectConfig, projectUpdate.addedPermissions());
+ addLabelPermissions(projectConfig, projectUpdate.addedLabelPermissions());
+ projectConfig.commit(metaDataUpdate);
+ }
+ projectCache.evict(nameKey);
+ }
+
+ private void addCapabilities(
+ ProjectConfig projectConfig, ImmutableList<TestCapability> addedCapabilities) {
+ for (TestCapability c : addedCapabilities) {
+ PermissionRule rule = Util.newRule(projectConfig, c.group());
+ rule.setRange(c.min(), c.max());
+ projectConfig
+ .getAccessSection(AccessSection.GLOBAL_CAPABILITIES, true)
+ .getPermission(c.name(), true)
+ .add(rule);
+ }
+ }
+
+ private void addPermissions(
+ ProjectConfig projectConfig, ImmutableList<TestPermission> addedPermissions) {
+ for (TestPermission p : addedPermissions) {
+ PermissionRule rule = Util.newRule(projectConfig, p.group());
+ rule.setAction(p.action());
+ rule.setForce(p.force());
+ projectConfig.getAccessSection(p.ref(), true).getPermission(p.name(), true).add(rule);
+ }
+ }
+
+ private void addLabelPermissions(
+ ProjectConfig projectConfig, ImmutableList<TestLabelPermission> addedLabelPermissions) {
+ for (TestLabelPermission p : addedLabelPermissions) {
+ PermissionRule rule = Util.newRule(projectConfig, p.group());
+ rule.setAction(p.action());
+ rule.setRange(p.min(), p.max());
+ Permission permission =
+ projectConfig
+ .getAccessSection(p.ref(), true)
+ .getPermission(Permission.forLabel(p.name()), true);
+ permission.setExclusiveGroup(p.exclusive());
+ permission.add(rule);
+ }
+ }
+
private RevCommit headOrNull(String branch) {
if (!branch.startsWith(Constants.R_REFS)) {
branch = RefNames.REFS_HEADS + branch;
@@ -98,5 +182,39 @@
throw new IllegalStateException(e);
}
}
+
+ @Override
+ public ProjectConfig getProjectConfig() {
+ try (Repository repo = repoManager.openRepository(nameKey)) {
+ ProjectConfig projectConfig = projectConfigFactory.create(nameKey);
+ projectConfig.load(nameKey, repo);
+ return projectConfig;
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public Config getConfig() {
+ try (Repository repo = repoManager.openRepository(nameKey);
+ RevWalk rw = new RevWalk(repo)) {
+ Ref ref = repo.exactRef(REFS_CONFIG);
+ if (ref == null) {
+ return new Config();
+ }
+ RevTree tree = rw.parseTree(ref.getObjectId());
+ TreeWalk tw = TreeWalk.forPath(rw.getObjectReader(), PROJECT_CONFIG, tree);
+ if (tw == null) {
+ return new Config();
+ }
+ ObjectLoader loader = rw.getObjectReader().open(tw.getObjectId(0));
+ String text = new String(loader.getCachedBytes(), UTF_8);
+ Config config = new Config();
+ config.fromText(text);
+ return config;
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
}
}
diff --git a/java/com/google/gerrit/acceptance/testsuite/project/TestProjectUpdate.java b/java/com/google/gerrit/acceptance/testsuite/project/TestProjectUpdate.java
new file mode 100644
index 0000000..b58eae6
--- /dev/null
+++ b/java/com/google/gerrit/acceptance/testsuite/project/TestProjectUpdate.java
@@ -0,0 +1,288 @@
+// 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.acceptance.testsuite.project;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+import com.google.gerrit.acceptance.testsuite.ThrowingConsumer;
+import com.google.gerrit.common.data.GlobalCapability;
+import com.google.gerrit.common.data.LabelType;
+import com.google.gerrit.common.data.Permission;
+import com.google.gerrit.common.data.PermissionRange;
+import com.google.gerrit.common.data.PermissionRule;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import java.util.Optional;
+
+@AutoValue
+public abstract class TestProjectUpdate {
+ /** Starts a builder for allowing a capability. */
+ public static TestCapability.Builder allowCapability(String name) {
+ return TestCapability.builder().name(name);
+ }
+
+ /** Records a global capability to be updated. */
+ @AutoValue
+ public abstract static class TestCapability {
+ private static Builder builder() {
+ return new AutoValue_TestProjectUpdate_TestCapability.Builder();
+ }
+
+ abstract String name();
+
+ abstract AccountGroup.UUID group();
+
+ abstract int min();
+
+ abstract int max();
+
+ /** Builder for {@link TestCapability}. */
+ @AutoValue.Builder
+ public abstract static class Builder {
+ /** Sets the name of the capability. */
+ public abstract Builder name(String name);
+
+ abstract String name();
+
+ /** Sets the group to which the capability applies. */
+ public abstract Builder group(AccountGroup.UUID group);
+
+ abstract Builder min(int min);
+
+ abstract Optional<Integer> min();
+
+ abstract Builder max(int max);
+
+ abstract Optional<Integer> max();
+
+ /** Sets the minimum and maximum values for the capability. */
+ public Builder range(int min, int max) {
+ return min(min).max(max);
+ }
+
+ /** Builds the {@link TestCapability}. */
+ abstract TestCapability autoBuild();
+
+ public TestCapability build() {
+ if (min().isPresent() || max().isPresent()) {
+ checkArgument(
+ GlobalCapability.hasRange(name()), "capability %s does not support ranges", name());
+ }
+ PermissionRange.WithDefaults withDefaults = GlobalCapability.getRange(name());
+ if (!min().isPresent()) {
+ min(withDefaults != null ? withDefaults.getDefaultMin() : 0);
+ }
+ if (!max().isPresent()) {
+ max(withDefaults != null ? withDefaults.getDefaultMax() : 0);
+ }
+ return autoBuild();
+ }
+ }
+ }
+
+ /** Starts a builder for allowing a permission. */
+ public static TestPermission.Builder allow(String name) {
+ return TestPermission.builder().name(name).action(PermissionRule.Action.ALLOW);
+ }
+
+ /** Starts a builder for denying a permission. */
+ public static TestPermission.Builder deny(String name) {
+ return TestPermission.builder().name(name).action(PermissionRule.Action.DENY);
+ }
+
+ /** Starts a builder for blocking a permission. */
+ public static TestPermission.Builder block(String name) {
+ return TestPermission.builder().name(name).action(PermissionRule.Action.BLOCK);
+ }
+
+ /**
+ * Records a permission to be updated.
+ *
+ * <p>Not used for permissions that have ranges (label permissions) or global capabilities.
+ */
+ @AutoValue
+ public abstract static class TestPermission {
+ private static Builder builder() {
+ return new AutoValue_TestProjectUpdate_TestPermission.Builder().force(false);
+ }
+
+ abstract String name();
+
+ abstract String ref();
+
+ abstract AccountGroup.UUID group();
+
+ abstract PermissionRule.Action action();
+
+ abstract boolean force();
+
+ /** Builder for {@link TestPermission}. */
+ @AutoValue.Builder
+ public abstract static class Builder {
+ abstract Builder name(String name);
+
+ /** Sets the ref pattern used on the permission. */
+ public abstract Builder ref(String ref);
+
+ /** Sets the group to which the permission applies. */
+ public abstract Builder group(AccountGroup.UUID groupUuid);
+
+ abstract Builder action(PermissionRule.Action action);
+
+ /** Sets whether the permission is a force permission. */
+ public abstract Builder force(boolean force);
+
+ /** Builds the {@link TestPermission}. */
+ public abstract TestPermission build();
+ }
+ }
+
+ /** Starts a builder for allowing a label permission. */
+ public static TestLabelPermission.Builder allowLabel(String name) {
+ return TestLabelPermission.builder().name(name).action(PermissionRule.Action.ALLOW);
+ }
+
+ /** Starts a builder for denying a label permission. */
+ public static TestLabelPermission.Builder blockLabel(String name) {
+ return TestLabelPermission.builder().name(name).action(PermissionRule.Action.BLOCK);
+ }
+
+ /** Records a label permission to be updated. */
+ @AutoValue
+ public abstract static class TestLabelPermission {
+ private static Builder builder() {
+ return new AutoValue_TestProjectUpdate_TestLabelPermission.Builder().exclusive(false);
+ }
+
+ abstract String name();
+
+ abstract String ref();
+
+ abstract AccountGroup.UUID group();
+
+ abstract PermissionRule.Action action();
+
+ abstract int min();
+
+ abstract int max();
+
+ abstract boolean exclusive();
+
+ /** Builder for {@link TestLabelPermission}. */
+ @AutoValue.Builder
+ public abstract static class Builder {
+ abstract Builder name(String name);
+
+ /** Sets the ref pattern used on the permission. */
+ public abstract Builder ref(String ref);
+
+ /** Sets the group to which the permission applies. */
+ public abstract Builder group(AccountGroup.UUID group);
+
+ abstract Builder action(PermissionRule.Action action);
+
+ abstract Builder min(int min);
+
+ abstract Builder max(int max);
+
+ /** Sets the minimum and maximum values for the permission. */
+ public Builder range(int min, int max) {
+ return min(min).max(max);
+ }
+
+ /** Adds the permission to the exclusive group permission set on the access section. */
+ public abstract Builder exclusive(boolean exclusive);
+
+ abstract TestLabelPermission autoBuild();
+
+ /** Builds the {@link TestPermission}. */
+ public TestLabelPermission build() {
+ TestLabelPermission result = autoBuild();
+ checkArgument(
+ !Permission.isLabel(result.name()),
+ "expected label name, got permission name: %s",
+ result.name());
+ LabelType.checkName(result.name());
+ return result;
+ }
+ }
+ }
+
+ static Builder builder(ThrowingConsumer<TestProjectUpdate> projectUpdater) {
+ return new AutoValue_TestProjectUpdate.Builder().projectUpdater(projectUpdater);
+ }
+
+ /** Builder for {@link TestProjectUpdate}. */
+ @AutoValue.Builder
+ public abstract static class Builder {
+ abstract ImmutableList.Builder<TestPermission> addedPermissionsBuilder();
+
+ abstract ImmutableList.Builder<TestLabelPermission> addedLabelPermissionsBuilder();
+
+ abstract ImmutableList.Builder<TestCapability> addedCapabilitiesBuilder();
+
+ /** Adds a permission to be included in this update. */
+ public Builder add(TestPermission testPermission) {
+ addedPermissionsBuilder().add(testPermission);
+ return this;
+ }
+
+ /** Adds a permission to be included in this update. */
+ public Builder add(TestPermission.Builder testPermissionBuilder) {
+ return add(testPermissionBuilder.build());
+ }
+
+ /** Adds a label permission to be included in this update. */
+ public Builder add(TestLabelPermission testLabelPermission) {
+ addedLabelPermissionsBuilder().add(testLabelPermission);
+ return this;
+ }
+
+ /** Adds a label permission to be included in this update. */
+ public Builder add(TestLabelPermission.Builder testLabelPermissionBuilder) {
+ return add(testLabelPermissionBuilder.build());
+ }
+
+ /** Adds a capability to be included in this update. */
+ public Builder add(TestCapability testCapability) {
+ addedCapabilitiesBuilder().add(testCapability);
+ return this;
+ }
+
+ /** Adds a capability to be included in this update. */
+ public Builder add(TestCapability.Builder testCapabilityBuilder) {
+ return add(testCapabilityBuilder.build());
+ }
+
+ abstract Builder projectUpdater(ThrowingConsumer<TestProjectUpdate> projectUpdater);
+
+ abstract TestProjectUpdate autoBuild();
+
+ /** Executes the update, updating the underlying project. */
+ public void update() {
+ TestProjectUpdate projectUpdate = autoBuild();
+ projectUpdate.projectUpdater().acceptAndThrowSilently(projectUpdate);
+ }
+ }
+
+ abstract ImmutableList<TestPermission> addedPermissions();
+
+ abstract ImmutableList<TestLabelPermission> addedLabelPermissions();
+
+ abstract ImmutableList<TestCapability> addedCapabilities();
+
+ abstract ThrowingConsumer<TestProjectUpdate> projectUpdater();
+}
diff --git a/java/com/google/gerrit/truth/BUILD b/java/com/google/gerrit/truth/BUILD
index 6f958b1..4727da1 100644
--- a/java/com/google/gerrit/truth/BUILD
+++ b/java/com/google/gerrit/truth/BUILD
@@ -6,6 +6,7 @@
deps = [
"//java/com/google/gerrit/common:annotations",
"//lib:guava",
+ "//lib/jgit/org.eclipse.jgit:jgit",
"//lib/truth",
],
)
diff --git a/java/com/google/gerrit/truth/ConfigSubject.java b/java/com/google/gerrit/truth/ConfigSubject.java
new file mode 100644
index 0000000..2a99151
--- /dev/null
+++ b/java/com/google/gerrit/truth/ConfigSubject.java
@@ -0,0 +1,129 @@
+// 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.truth;
+
+import static com.google.common.truth.Truth.assertAbout;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ImmutableListMultimap;
+import com.google.common.truth.BooleanSubject;
+import com.google.common.truth.FailureMetadata;
+import com.google.common.truth.IntegerSubject;
+import com.google.common.truth.IterableSubject;
+import com.google.common.truth.ListMultimapSubject;
+import com.google.common.truth.LongSubject;
+import com.google.common.truth.StringSubject;
+import com.google.common.truth.Subject;
+import com.google.gerrit.common.Nullable;
+import java.util.Arrays;
+import org.eclipse.jgit.lib.Config;
+
+public class ConfigSubject extends Subject<ConfigSubject, Config> {
+ public static ConfigSubject assertThat(Config config) {
+ return assertAbout(ConfigSubject::new).that(config);
+ }
+
+ private final Config config;
+
+ private ConfigSubject(FailureMetadata metadata, Config actual) {
+ super(metadata, actual);
+ this.config = actual;
+ }
+
+ public IterableSubject sections() {
+ isNotNull();
+ return check("getSections()").that(config.getSections());
+ }
+
+ public IterableSubject subsections(String section) {
+ requireNonNull(section);
+ isNotNull();
+ return check("getSubsections(%s)", section).that(config.getSubsections(section));
+ }
+
+ public ListMultimapSubject sectionValues(String section) {
+ requireNonNull(section);
+ return sectionValuesImpl(section, null);
+ }
+
+ public ListMultimapSubject subsectionValues(String section, String subsection) {
+ requireNonNull(section);
+ requireNonNull(subsection);
+ return sectionValuesImpl(section, subsection);
+ }
+
+ private ListMultimapSubject sectionValuesImpl(String section, @Nullable String subsection) {
+ isNotNull();
+ ImmutableListMultimap.Builder<String, String> b = ImmutableListMultimap.builder();
+ config
+ .getNames(section, subsection, true)
+ .forEach(
+ n ->
+ Arrays.stream(config.getStringList(section, subsection, n))
+ .forEach(v -> b.put(n, v)));
+ return check("getSection(%s, %s)", section, subsection).that(b.build());
+ }
+
+ public void isEmpty() {
+ sections().isEmpty();
+ }
+
+ public StringSubject text() {
+ isNotNull();
+ return check("toText()").that(config.toText());
+ }
+
+ public IterableSubject stringValues(String section, @Nullable String subsection, String name) {
+ requireNonNull(section);
+ requireNonNull(name);
+ isNotNull();
+ return check("getStringList(%s, %s, %s)", section, subsection, name)
+ .that(Arrays.asList(config.getStringList(section, subsection, name)));
+ }
+
+ public StringSubject stringValue(String section, @Nullable String subsection, String name) {
+ requireNonNull(section);
+ requireNonNull(name);
+ isNotNull();
+ return check("getString(%s, %s, %s)", section, subsection, name)
+ .that(config.getString(section, subsection, name));
+ }
+
+ public IntegerSubject intValue(
+ String section, @Nullable String subsection, String name, int defaultValue) {
+ requireNonNull(section);
+ requireNonNull(name);
+ isNotNull();
+ return check("getInt(%s, %s, %s, %s)", section, subsection, name, defaultValue)
+ .that(config.getInt(section, subsection, name, defaultValue));
+ }
+
+ public LongSubject longValue(String section, String subsection, String name, long defaultValue) {
+ requireNonNull(section);
+ requireNonNull(name);
+ isNotNull();
+ return check("getLong(%s, %s, %s, %s)", section, subsection, name, defaultValue)
+ .that(config.getLong(section, subsection, name, defaultValue));
+ }
+
+ public BooleanSubject booleanValue(
+ String section, String subsection, String name, boolean defaultValue) {
+ requireNonNull(section);
+ requireNonNull(name);
+ isNotNull();
+ return check("getBoolean(%s, %s, %s, %s)", section, subsection, name, defaultValue)
+ .that(config.getBoolean(section, subsection, name, defaultValue));
+ }
+}
diff --git a/javatests/com/google/gerrit/acceptance/BUILD b/javatests/com/google/gerrit/acceptance/BUILD
index 54b3626..405610b 100644
--- a/javatests/com/google/gerrit/acceptance/BUILD
+++ b/javatests/com/google/gerrit/acceptance/BUILD
@@ -7,6 +7,7 @@
"//java/com/google/gerrit/acceptance:lib",
"//java/com/google/gerrit/server/util/time",
"//java/com/google/gerrit/testing:gerrit-test-util",
+ "//java/com/google/gerrit/truth",
"//lib:guava",
"//lib/jgit/org.eclipse.jgit:jgit",
"//lib/truth",
diff --git a/javatests/com/google/gerrit/acceptance/MergeableFileBasedConfigTest.java b/javatests/com/google/gerrit/acceptance/MergeableFileBasedConfigTest.java
index 49c23e3..3d17de0 100644
--- a/javatests/com/google/gerrit/acceptance/MergeableFileBasedConfigTest.java
+++ b/javatests/com/google/gerrit/acceptance/MergeableFileBasedConfigTest.java
@@ -15,6 +15,7 @@
package com.google.gerrit.acceptance;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.gerrit.truth.ConfigSubject.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.collect.ImmutableList;
@@ -111,7 +112,7 @@
}
private void assertConfig(MergeableFileBasedConfig cfg, String expected) throws Exception {
- assertThat(cfg.toText()).isEqualTo(expected);
+ assertThat(cfg).text().isEqualTo(expected);
cfg.save();
assertThat(new String(Files.readAllBytes(cfg.getFile().toPath()), UTF_8)).isEqualTo(expected);
}
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
index 6e35c2d..fc04204 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
@@ -33,6 +33,7 @@
import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
+import static com.google.gerrit.truth.ConfigSubject.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.SECONDS;
@@ -477,10 +478,11 @@
assertThat(tw).isNotNull();
Config cfg = new Config();
cfg.fromText(new String(or.open(tw.getObjectId(0), OBJ_BLOB).getBytes(), UTF_8));
- assertThat(
- cfg.getString(AccountProperties.ACCOUNT, null, AccountProperties.KEY_FULL_NAME))
+ assertThat(cfg)
+ .stringValue(AccountProperties.ACCOUNT, null, AccountProperties.KEY_FULL_NAME)
.isEqualTo(name);
- assertThat(cfg.getString(AccountProperties.ACCOUNT, null, AccountProperties.KEY_STATUS))
+ assertThat(cfg)
+ .stringValue(AccountProperties.ACCOUNT, null, AccountProperties.KEY_STATUS)
.isEqualTo(status);
} else {
// No account properties were set, hence an 'account.config' file was not created.
@@ -1537,7 +1539,7 @@
accountIndexedCounter.clear();
grant(allUsers, userRef, Permission.PUSH, false, adminGroupUuid());
- grantLabel("Code-Review", -2, 2, allUsers, userRef, false, adminGroupUuid(), false);
+ grantLabel("Code-Review", -2, 2, allUsers, userRef, adminGroupUuid(), false);
grant(allUsers, userRef, Permission.SUBMIT, false, adminGroupUuid());
TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
diff --git a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
index 09c0631..28ebadb 100644
--- a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
@@ -1415,8 +1415,7 @@
private void pushToGroupBranchForReviewAndSubmit(
Project.NameKey project, String groupRef, String expectedError) throws Throwable {
- grantLabel(
- "Code-Review", -2, 2, project, RefNames.REFS_GROUPS + "*", false, REGISTERED_USERS, false);
+ grantLabel("Code-Review", -2, 2, project, RefNames.REFS_GROUPS + "*", REGISTERED_USERS, false);
grant(project, RefNames.REFS_GROUPS + "*", Permission.SUBMIT, false, REGISTERED_USERS);
TestRepository<InMemoryRepository> repo = cloneProject(project);
diff --git a/javatests/com/google/gerrit/acceptance/git/ForcePushIT.java b/javatests/com/google/gerrit/acceptance/git/ForcePushIT.java
index eb4845e..b895ddf 100644
--- a/javatests/com/google/gerrit/acceptance/git/ForcePushIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/ForcePushIT.java
@@ -82,7 +82,7 @@
@Test
public void deleteNotAllowedWithOnlyPushPermission() throws Exception {
- grant(project, "refs/*", Permission.PUSH, false);
+ grant(project, "refs/*", Permission.PUSH);
assertDeleteRef(REJECTED_OTHER_REASON);
}
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
index 75c17bf..39a29cc 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
@@ -40,7 +40,6 @@
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.TestProjectInput;
-import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.data.Permission;
@@ -123,7 +122,6 @@
@Inject private ApprovalsUtil approvalsUtil;
@Inject private DynamicSet<OnSubmitValidationListener> onSubmitValidationListeners;
@Inject private IdentifiedUser.GenericFactory userFactory;
- @Inject private ProjectOperations projectOperations;
@Inject private RequestScopeOperations requestScopeOperations;
@Inject private Submit submitHandler;
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/ChangeOwnerIT.java b/javatests/com/google/gerrit/acceptance/rest/change/ChangeOwnerIT.java
index 41f3147..70abe24 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/ChangeOwnerIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/ChangeOwnerIT.java
@@ -140,7 +140,7 @@
private void grantApprove(Project.NameKey project, AccountGroup.UUID groupUUID, boolean exclusive)
throws Exception {
- grantLabel("Code-Review", -2, 2, project, "refs/heads/*", false, groupUUID, exclusive);
+ grantLabel("Code-Review", -2, 2, project, "refs/heads/*", groupUUID, exclusive);
}
private void blockApproveForChangeOwner(Project.NameKey project) throws Exception {
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/ConfigChangeIT.java b/javatests/com/google/gerrit/acceptance/rest/change/ConfigChangeIT.java
index 9a907aa..a4ca7a3 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/ConfigChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/ConfigChangeIT.java
@@ -16,7 +16,7 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
-import static java.nio.charset.StandardCharsets.UTF_8;
+import static com.google.gerrit.truth.ConfigSubject.assertThat;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.GitUtil;
@@ -36,10 +36,6 @@
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.ObjectLoader;
-import org.eclipse.jgit.revwalk.RevObject;
-import org.eclipse.jgit.revwalk.RevTree;
-import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.RefSpec;
import org.junit.Before;
import org.junit.Test;
@@ -75,8 +71,8 @@
}
private String testUpdateProjectConfig() throws Exception {
- Config cfg = readProjectConfig();
- assertThat(cfg.getString("project", null, "description")).isNull();
+ Config cfg = projectOperations.project(project).getConfig();
+ assertThat(cfg).stringValue("project", null, "description").isNull();
String desc = "new project description";
cfg.setString("project", null, "description", desc);
@@ -89,7 +85,12 @@
assertThat(gApi.changes().id(id).info().status).isEqualTo(ChangeStatus.MERGED);
assertThat(gApi.projects().name(project.get()).get().description).isEqualTo(desc);
fetchRefsMetaConfig();
- assertThat(readProjectConfig().getString("project", null, "description")).isEqualTo(desc);
+ assertThat(
+ projectOperations
+ .project(project)
+ .getConfig()
+ .getString("project", null, "description"))
+ .isEqualTo(desc);
String changeRev = gApi.changes().id(id).get().currentRevision;
String branchRev =
gApi.projects().name(project.get()).branch(RefNames.REFS_CONFIG).get().revision;
@@ -107,8 +108,8 @@
gApi.projects().create(parent);
requestScopeOperations.setApiUser(user.id());
- Config cfg = readProjectConfig();
- assertThat(cfg.getString("access", null, "inheritFrom")).isAnyOf(null, allProjects.get());
+ Config cfg = projectOperations.project(project).getConfig();
+ assertThat(cfg).stringValue("access", null, "inheritFrom").isAnyOf(null, allProjects.get());
cfg.setString("access", null, "inheritFrom", parent.name);
PushOneCommit.Result r = createConfigChange(cfg);
@@ -133,7 +134,8 @@
assertThat(gApi.projects().name(project.get()).get().parent).isEqualTo(allProjects.get());
fetchRefsMetaConfig();
- assertThat(readProjectConfig().getString("access", null, "inheritFrom"))
+ assertThat(
+ projectOperations.project(project).getConfig().getString("access", null, "inheritFrom"))
.isAnyOf(null, allProjects.get());
requestScopeOperations.setApiUser(admin.id());
@@ -141,7 +143,9 @@
assertThat(gApi.changes().id(id).info().status).isEqualTo(ChangeStatus.MERGED);
assertThat(gApi.projects().name(project.get()).get().parent).isEqualTo(parent.name);
fetchRefsMetaConfig();
- assertThat(readProjectConfig().getString("access", null, "inheritFrom")).isEqualTo(parent.name);
+ assertThat(
+ projectOperations.project(project).getConfig().getString("access", null, "inheritFrom"))
+ .isEqualTo(parent.name);
}
@Test
@@ -179,17 +183,6 @@
testRepo.reset(RefNames.REFS_CONFIG);
}
- private Config readProjectConfig() throws Exception {
- RevWalk rw = testRepo.getRevWalk();
- RevTree tree = rw.parseTree(testRepo.getRepository().resolve("HEAD"));
- RevObject obj = rw.parseAny(testRepo.get(tree, "project.config"));
- ObjectLoader loader = rw.getObjectReader().open(obj);
- String text = new String(loader.getCachedBytes(), UTF_8);
- Config cfg = new Config();
- cfg.fromText(text);
- return cfg;
- }
-
private PushOneCommit.Result createConfigChange(Config cfg) throws Exception {
PushOneCommit.Result r =
pushFactory
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/SubmitByMergeIfNecessaryIT.java b/javatests/com/google/gerrit/acceptance/rest/change/SubmitByMergeIfNecessaryIT.java
index f53ff23..ab9eed4 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/SubmitByMergeIfNecessaryIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/SubmitByMergeIfNecessaryIT.java
@@ -607,7 +607,7 @@
@Test
public void dependencyOnChangeForNonVisibleBranchPreventsMerge() throws Throwable {
- grantLabel("Code-Review", -2, 2, project, "refs/heads/*", false, REGISTERED_USERS, false);
+ grantLabel("Code-Review", -2, 2, project, "refs/heads/*", REGISTERED_USERS, false);
grant(project, "refs/*", Permission.SUBMIT, false, REGISTERED_USERS);
// Create a change
@@ -662,7 +662,7 @@
@Test
public void dependencyOnHiddenChangePreventsMerge() throws Throwable {
- grantLabel("Code-Review", -2, 2, project, "refs/heads/*", false, REGISTERED_USERS, false);
+ grantLabel("Code-Review", -2, 2, project, "refs/heads/*", REGISTERED_USERS, false);
grant(project, "refs/*", Permission.SUBMIT, false, REGISTERED_USERS);
// Create a change
@@ -716,9 +716,9 @@
Project.NameKey p1 = projectOperations.newProject().create();
Project.NameKey p2 = projectOperations.newProject().create();
- grantLabel("Code-Review", -2, 2, p1, "refs/heads/*", false, REGISTERED_USERS, false);
+ grantLabel("Code-Review", -2, 2, p1, "refs/heads/*", REGISTERED_USERS, false);
grant(p1, "refs/*", Permission.SUBMIT, false, REGISTERED_USERS);
- grantLabel("Code-Review", -2, 2, p2, "refs/heads/*", false, REGISTERED_USERS, false);
+ grantLabel("Code-Review", -2, 2, p2, "refs/heads/*", REGISTERED_USERS, false);
grant(p2, "refs/*", Permission.SUBMIT, false, REGISTERED_USERS);
TestRepository<?> repo1 = cloneProject(p1);
diff --git a/javatests/com/google/gerrit/acceptance/rest/project/AccessIT.java b/javatests/com/google/gerrit/acceptance/rest/project/AccessIT.java
index 8d62765..503ebcc 100644
--- a/javatests/com/google/gerrit/acceptance/rest/project/AccessIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/project/AccessIT.java
@@ -18,6 +18,7 @@
import static com.google.gerrit.extensions.client.ListChangesOption.MESSAGES;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
+import static com.google.gerrit.truth.ConfigSubject.assertThat;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.GitUtil;
@@ -568,7 +569,7 @@
.file(ProjectConfig.PROJECT_CONFIG)
.asString();
cfg.fromText(config);
- assertThat(cfg.getString(access, refsFor, unknownPermission)).isEqualTo(registeredUsers);
+ assertThat(cfg).stringValue(access, refsFor, unknownPermission).isEqualTo(registeredUsers);
// Make permission change through API
ProjectAccessInput accessInput = newProjectAccessInput();
@@ -587,7 +588,7 @@
.file(ProjectConfig.PROJECT_CONFIG)
.asString();
cfg.fromText(config);
- assertThat(cfg.getString(access, refsFor, unknownPermission)).isEqualTo(registeredUsers);
+ assertThat(cfg).stringValue(access, refsFor, unknownPermission).isEqualTo(registeredUsers);
}
@Test
diff --git a/javatests/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java b/javatests/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java
index 9492536..f95342a 100644
--- a/javatests/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java
@@ -23,6 +23,7 @@
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.RestResponse;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
+import com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.extensions.api.projects.BranchApi;
@@ -134,8 +135,18 @@
@Test
public void deleteUserBranch_Conflict() throws Exception {
- allow(allUsers, RefNames.REFS_USERS + "*", Permission.CREATE, REGISTERED_USERS);
- allow(allUsers, RefNames.REFS_USERS + "*", Permission.PUSH, REGISTERED_USERS);
+ projectOperations
+ .project(allUsers)
+ .forUpdate()
+ .add(
+ TestProjectUpdate.allow(Permission.CREATE)
+ .ref(RefNames.REFS_USERS + "*")
+ .group(REGISTERED_USERS))
+ .add(
+ TestProjectUpdate.allow(Permission.PUSH)
+ .ref(RefNames.REFS_USERS + "*")
+ .group(REGISTERED_USERS))
+ .update();
ResourceConflictException thrown =
assertThrows(
@@ -159,7 +170,15 @@
}
private void blockForcePush() throws Exception {
- block("refs/heads/*", Permission.PUSH, ANONYMOUS_USERS).setForce(true);
+ projectOperations
+ .project(project)
+ .forUpdate()
+ .add(
+ TestProjectUpdate.block(Permission.PUSH)
+ .ref("refs/heads/*")
+ .group(ANONYMOUS_USERS)
+ .force(true))
+ .update();
}
private void grantForcePush() throws Exception {
diff --git a/javatests/com/google/gerrit/acceptance/rest/project/DeleteTagIT.java b/javatests/com/google/gerrit/acceptance/rest/project/DeleteTagIT.java
index bc0e2ea..892c375 100644
--- a/javatests/com/google/gerrit/acceptance/rest/project/DeleteTagIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/project/DeleteTagIT.java
@@ -22,6 +22,7 @@
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.RestResponse;
+import com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.extensions.api.projects.TagApi;
@@ -98,7 +99,15 @@
}
private void blockForcePush() throws Exception {
- block("refs/tags/*", Permission.PUSH, ANONYMOUS_USERS).setForce(true);
+ projectOperations
+ .project(project)
+ .forUpdate()
+ .add(
+ TestProjectUpdate.block(Permission.PUSH)
+ .ref("refs/tags/*")
+ .group(ANONYMOUS_USERS)
+ .force(true))
+ .update();
}
private void grantForcePush() throws Exception {
diff --git a/javatests/com/google/gerrit/acceptance/testsuite/project/ProjectOperationsImplTest.java b/javatests/com/google/gerrit/acceptance/testsuite/project/ProjectOperationsImplTest.java
index 3f537c0..8ecd21c 100644
--- a/javatests/com/google/gerrit/acceptance/testsuite/project/ProjectOperationsImplTest.java
+++ b/javatests/com/google/gerrit/acceptance/testsuite/project/ProjectOperationsImplTest.java
@@ -15,14 +15,31 @@
package com.google.gerrit.acceptance.testsuite.project;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowCapability;
+import static com.google.gerrit.common.data.GlobalCapability.ADMINISTRATE_SERVER;
+import static com.google.gerrit.common.data.GlobalCapability.DEFAULT_MAX_QUERY_LIMIT;
+import static com.google.gerrit.common.data.GlobalCapability.QUERY_LIMIT;
+import static com.google.gerrit.reviewdb.client.RefNames.REFS_CONFIG;
+import static com.google.gerrit.server.group.SystemGroupBackend.PROJECT_OWNERS;
+import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
+import static com.google.gerrit.truth.ConfigSubject.assertThat;
import static java.util.stream.Collectors.toList;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.TestPermission;
+import com.google.gerrit.common.data.Permission;
import com.google.gerrit.extensions.api.projects.BranchInfo;
+import com.google.gerrit.extensions.api.projects.ConfigInput;
import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.server.project.ProjectConfig;
+import com.google.gerrit.server.project.ProjectState;
import com.google.inject.Inject;
import java.util.List;
+import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.StoredConfig;
import org.junit.Test;
public class ProjectOperationsImplTest extends AbstractDaemonTest {
@@ -48,9 +65,322 @@
@Test
public void emptyCommit() throws Exception {
Project.NameKey key = projectOperations.newProject().create();
+
List<BranchInfo> branches = gApi.projects().name(key.get()).branches().get();
assertThat(branches).isNotEmpty();
assertThat(branches.stream().map(x -> x.ref).collect(toList()))
.isEqualTo(ImmutableList.of("HEAD", "refs/meta/config", "refs/heads/master"));
}
+
+ @Test
+ public void getProjectConfig() throws Exception {
+ Project.NameKey key = projectOperations.newProject().create();
+ assertThat(projectOperations.project(key).getProjectConfig().getProject().getDescription())
+ .isEmpty();
+
+ ConfigInput input = new ConfigInput();
+ input.description = "my fancy project";
+ gApi.projects().name(key.get()).config(input);
+
+ assertThat(projectOperations.project(key).getProjectConfig().getProject().getDescription())
+ .isEqualTo("my fancy project");
+ }
+
+ @Test
+ public void mutatingResultOfGetProjectConfigDoesNotMutateGlobalCachedValue() throws Exception {
+ Project.NameKey key = projectOperations.newProject().create();
+ ProjectConfig projectConfig = projectOperations.project(key).getProjectConfig();
+ ProjectState cachedProjectState1 = projectCache.checkedGet(key);
+ ProjectConfig cachedProjectConfig1 = cachedProjectState1.getConfig();
+ assertThat(cachedProjectConfig1).isNotSameInstanceAs(projectConfig);
+ assertThat(cachedProjectConfig1.getProject().getDescription()).isEmpty();
+ assertThat(projectConfig.getProject().getDescription()).isEmpty();
+ projectConfig.getProject().setDescription("my fancy project");
+
+ ProjectConfig cachedProjectConfig2 = projectCache.checkedGet(key).getConfig();
+ assertThat(cachedProjectConfig2).isNotSameInstanceAs(projectConfig);
+ assertThat(cachedProjectConfig2.getProject().getDescription()).isEmpty();
+ }
+
+ @Test
+ public void getProjectConfigNoRefsMetaConfig() throws Exception {
+ Project.NameKey key = projectOperations.newProject().create();
+ deleteRefsMetaConfig(key);
+
+ ProjectConfig projectConfig = projectOperations.project(key).getProjectConfig();
+ assertThat(projectConfig.getName()).isEqualTo(key);
+ assertThat(projectConfig.getRevision()).isNull();
+ }
+
+ @Test
+ public void getConfig() throws Exception {
+ Project.NameKey key = projectOperations.newProject().create();
+ Config config = projectOperations.project(key).getConfig();
+ assertThat(config).isNotInstanceOf(StoredConfig.class);
+ assertThat(config).text().isEmpty();
+
+ ConfigInput input = new ConfigInput();
+ input.description = "my fancy project";
+ gApi.projects().name(key.get()).config(input);
+
+ config = projectOperations.project(key).getConfig();
+ assertThat(config).isNotInstanceOf(StoredConfig.class);
+ assertThat(config).sections().containsExactly("project");
+ assertThat(config).subsections("project").isEmpty();
+ assertThat(config).sectionValues("project").containsExactly("description", "my fancy project");
+ }
+
+ @Test
+ public void getConfigNoRefsMetaConfig() throws Exception {
+ Project.NameKey key = projectOperations.newProject().create();
+ deleteRefsMetaConfig(key);
+
+ Config config = projectOperations.project(key).getConfig();
+ assertThat(config).isNotInstanceOf(StoredConfig.class);
+ assertThat(config).isEmpty();
+ }
+
+ @Test
+ public void addAllowPermission() throws Exception {
+ Project.NameKey key = projectOperations.newProject().create();
+ projectOperations
+ .project(key)
+ .forUpdate()
+ .add(TestProjectUpdate.allow(Permission.ABANDON).ref("refs/foo").group(REGISTERED_USERS))
+ .update();
+
+ Config config = projectOperations.project(key).getConfig();
+ assertThat(config).sections().containsExactly("access");
+ assertThat(config).subsections("access").containsExactly("refs/foo");
+ assertThat(config)
+ .subsectionValues("access", "refs/foo")
+ .containsExactly("abandon", "group global:Registered-Users");
+ }
+
+ @Test
+ public void addDenyPermission() throws Exception {
+ Project.NameKey key = projectOperations.newProject().create();
+ projectOperations
+ .project(key)
+ .forUpdate()
+ .add(TestProjectUpdate.deny(Permission.ABANDON).ref("refs/foo").group(REGISTERED_USERS))
+ .update();
+
+ Config config = projectOperations.project(key).getConfig();
+ assertThat(config).sections().containsExactly("access");
+ assertThat(config).subsections("access").containsExactly("refs/foo");
+ assertThat(config)
+ .subsectionValues("access", "refs/foo")
+ .containsExactly("abandon", "deny group global:Registered-Users");
+ }
+
+ @Test
+ public void addBlockPermission() throws Exception {
+ Project.NameKey key = projectOperations.newProject().create();
+ projectOperations
+ .project(key)
+ .forUpdate()
+ .add(TestProjectUpdate.block(Permission.ABANDON).ref("refs/foo").group(REGISTERED_USERS))
+ .update();
+
+ Config config = projectOperations.project(key).getConfig();
+ assertThat(config).sections().containsExactly("access");
+ assertThat(config).subsections("access").containsExactly("refs/foo");
+ assertThat(config)
+ .subsectionValues("access", "refs/foo")
+ .containsExactly("abandon", "block group global:Registered-Users");
+ }
+
+ @Test
+ public void addAllowForcePermission() throws Exception {
+ Project.NameKey key = projectOperations.newProject().create();
+ projectOperations
+ .project(key)
+ .forUpdate()
+ .add(
+ TestProjectUpdate.allow(Permission.ABANDON)
+ .ref("refs/foo")
+ .group(REGISTERED_USERS)
+ .force(true))
+ .update();
+
+ Config config = projectOperations.project(key).getConfig();
+ assertThat(config).sections().containsExactly("access");
+ assertThat(config).subsections("access").containsExactly("refs/foo");
+ assertThat(config)
+ .subsectionValues("access", "refs/foo")
+ .containsExactly("abandon", "+force group global:Registered-Users");
+ }
+
+ @Test
+ public void addMultiplePermissions() throws Exception {
+ Project.NameKey key = projectOperations.newProject().create();
+ projectOperations
+ .project(key)
+ .forUpdate()
+ .add(TestProjectUpdate.allow(Permission.ABANDON).ref("refs/foo").group(PROJECT_OWNERS))
+ .add(TestProjectUpdate.allow(Permission.CREATE).ref("refs/foo").group(REGISTERED_USERS))
+ .update();
+
+ Config config = projectOperations.project(key).getConfig();
+ assertThat(config).sections().containsExactly("access");
+ assertThat(config).subsections("access").containsExactly("refs/foo");
+ assertThat(config)
+ .subsectionValues("access", "refs/foo")
+ .containsExactly(
+ "abandon", "group global:Project-Owners",
+ "create", "group global:Registered-Users");
+ }
+
+ @Test
+ public void addDuplicatePermissions() throws Exception {
+ TestPermission permission =
+ TestProjectUpdate.allow(Permission.ABANDON).ref("refs/foo").group(REGISTERED_USERS).build();
+ Project.NameKey key = projectOperations.newProject().create();
+ projectOperations.project(key).forUpdate().add(permission).add(permission).update();
+
+ Config config = projectOperations.project(key).getConfig();
+ assertThat(config).sections().containsExactly("access");
+ assertThat(config).subsections("access").containsExactly("refs/foo");
+ assertThat(config)
+ .subsectionValues("access", "refs/foo")
+ .containsExactly(
+ "abandon", "group global:Registered-Users",
+ "abandon", "group global:Registered-Users");
+
+ projectOperations.project(key).forUpdate().add(permission).update();
+ config = projectOperations.project(key).getConfig();
+ assertThat(config).sections().containsExactly("access");
+ assertThat(config).subsections("access").containsExactly("refs/foo");
+ assertThat(config)
+ .subsectionValues("access", "refs/foo")
+ .containsExactly(
+ "abandon", "group global:Registered-Users",
+ "abandon", "group global:Registered-Users",
+ "abandon", "group global:Registered-Users");
+ }
+
+ @Test
+ public void addAllowLabelPermission() throws Exception {
+ Project.NameKey key = projectOperations.newProject().create();
+ projectOperations
+ .project(key)
+ .forUpdate()
+ .add(
+ TestProjectUpdate.allowLabel("Code-Review")
+ .ref("refs/foo")
+ .group(REGISTERED_USERS)
+ .range(-1, 2))
+ .update();
+
+ Config config = projectOperations.project(key).getConfig();
+ assertThat(config).sections().containsExactly("access");
+ assertThat(config).subsections("access").containsExactly("refs/foo");
+ assertThat(config)
+ .subsectionValues("access", "refs/foo")
+ .containsExactly("label-Code-Review", "-1..+2 group global:Registered-Users");
+ }
+
+ @Test
+ public void addBlockLabelPermission() throws Exception {
+ Project.NameKey key = projectOperations.newProject().create();
+ projectOperations
+ .project(key)
+ .forUpdate()
+ .add(
+ TestProjectUpdate.blockLabel("Code-Review")
+ .ref("refs/foo")
+ .group(REGISTERED_USERS)
+ .range(-1, 2))
+ .update();
+
+ Config config = projectOperations.project(key).getConfig();
+ assertThat(config).sections().containsExactly("access");
+ assertThat(config).subsections("access").containsExactly("refs/foo");
+ assertThat(config)
+ .subsectionValues("access", "refs/foo")
+ .containsExactly("label-Code-Review", "block -1..+2 group global:Registered-Users");
+ }
+
+ @Test
+ public void addAllowExclusiveLabelPermission() throws Exception {
+ Project.NameKey key = projectOperations.newProject().create();
+ projectOperations
+ .project(key)
+ .forUpdate()
+ .add(
+ TestProjectUpdate.allowLabel("Code-Review")
+ .ref("refs/foo")
+ .group(REGISTERED_USERS)
+ .range(-1, 2)
+ .exclusive(true))
+ .update();
+
+ Config config = projectOperations.project(key).getConfig();
+ assertThat(config).sections().containsExactly("access");
+ assertThat(config).subsections("access").containsExactly("refs/foo");
+ assertThat(config)
+ .subsectionValues("access", "refs/foo")
+ .containsExactly(
+ "label-Code-Review", "-1..+2 group global:Registered-Users",
+ "exclusiveGroupPermissions", "label-Code-Review");
+ }
+
+ @Test
+ public void addAllowCapability() throws Exception {
+ Project.NameKey key = projectOperations.newProject().create();
+ projectOperations
+ .project(key)
+ .forUpdate()
+ .add(allowCapability(ADMINISTRATE_SERVER).group(REGISTERED_USERS))
+ .update();
+
+ Config config = projectOperations.project(key).getConfig();
+ assertThat(config).sections().containsExactly("capability");
+ assertThat(config).subsections("capability").isEmpty();
+ assertThat(config)
+ .sectionValues("capability")
+ .containsExactly("administrateServer", "group global:Registered-Users");
+ }
+
+ @Test
+ public void addAllowCapabilityWithRange() throws Exception {
+ Project.NameKey key = projectOperations.newProject().create();
+ projectOperations
+ .project(key)
+ .forUpdate()
+ .add(allowCapability(QUERY_LIMIT).group(REGISTERED_USERS).range(0, 5000))
+ .update();
+
+ Config config = projectOperations.project(key).getConfig();
+ assertThat(config).sections().containsExactly("capability");
+ assertThat(config).subsections("capability").isEmpty();
+ assertThat(config)
+ .sectionValues("capability")
+ .containsExactly("queryLimit", "+0..+5000 group global:Registered-Users");
+ }
+
+ @Test
+ public void addAllowCapabilityWithDefaultRange() throws Exception {
+ Project.NameKey key = projectOperations.newProject().create();
+ projectOperations
+ .project(key)
+ .forUpdate()
+ .add(allowCapability(QUERY_LIMIT).group(REGISTERED_USERS))
+ .update();
+
+ Config config = projectOperations.project(key).getConfig();
+ assertThat(config).sections().containsExactly("capability");
+ assertThat(config).subsections("capability").isEmpty();
+ assertThat(config)
+ .sectionValues("capability")
+ .containsExactly(
+ "queryLimit", "+0..+" + DEFAULT_MAX_QUERY_LIMIT + " group global:Registered-Users");
+ }
+
+ private void deleteRefsMetaConfig(Project.NameKey key) throws Exception {
+ try (Repository repo = repoManager.openRepository(key)) {
+ new TestRepository<>(repo).delete(REFS_CONFIG);
+ }
+ }
}
diff --git a/javatests/com/google/gerrit/server/config/ConfigUtilTest.java b/javatests/com/google/gerrit/server/config/ConfigUtilTest.java
index 231b584..865bda6 100644
--- a/javatests/com/google/gerrit/server/config/ConfigUtilTest.java
+++ b/javatests/com/google/gerrit/server/config/ConfigUtilTest.java
@@ -15,6 +15,7 @@
package com.google.gerrit.server.config;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.gerrit.truth.ConfigSubject.assertThat;
import static java.util.concurrent.TimeUnit.DAYS;
import static java.util.concurrent.TimeUnit.HOURS;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
@@ -90,17 +91,17 @@
Config cfg = new Config();
ConfigUtil.storeSection(cfg, SECT, SUB, in, d);
- assertThat(cfg.getString(SECT, SUB, "CONSTANT")).isNull();
- assertThat(cfg.getString(SECT, SUB, "missing")).isNull();
- assertThat(cfg.getBoolean(SECT, SUB, "b", false)).isEqualTo(in.b);
- assertThat(cfg.getBoolean(SECT, SUB, "bb", false)).isEqualTo(in.bb);
- assertThat(cfg.getInt(SECT, SUB, "i", 0)).isEqualTo(0);
- assertThat(cfg.getInt(SECT, SUB, "ii", 0)).isEqualTo(in.ii);
- assertThat(cfg.getLong(SECT, SUB, "l", 0L)).isEqualTo(0L);
- assertThat(cfg.getLong(SECT, SUB, "ll", 0L)).isEqualTo(in.ll);
- assertThat(cfg.getString(SECT, SUB, "s")).isEqualTo(in.s);
- assertThat(cfg.getString(SECT, SUB, "sd")).isNull();
- assertThat(cfg.getString(SECT, SUB, "nd")).isNull();
+ assertThat(cfg).stringValue(SECT, SUB, "CONSTANT").isNull();
+ assertThat(cfg).stringValue(SECT, SUB, "missing").isNull();
+ assertThat(cfg).booleanValue(SECT, SUB, "b", false).isEqualTo(in.b);
+ assertThat(cfg).booleanValue(SECT, SUB, "bb", false).isEqualTo(in.bb);
+ assertThat(cfg).intValue(SECT, SUB, "i", 0).isEqualTo(0);
+ assertThat(cfg).intValue(SECT, SUB, "ii", 0).isEqualTo(in.ii);
+ assertThat(cfg).longValue(SECT, SUB, "l", 0L).isEqualTo(0L);
+ assertThat(cfg).longValue(SECT, SUB, "ll", 0L).isEqualTo(in.ll);
+ assertThat(cfg).stringValue(SECT, SUB, "s").isEqualTo(in.s);
+ assertThat(cfg).stringValue(SECT, SUB, "sd").isNull();
+ assertThat(cfg).stringValue(SECT, SUB, "nd").isNull();
SectionInfo out = new SectionInfo();
ConfigUtil.loadSection(cfg, SECT, SUB, out, d, null);
diff --git a/javatests/com/google/gerrit/server/schema/AllProjectsCreatorTest.java b/javatests/com/google/gerrit/server/schema/AllProjectsCreatorTest.java
index 5f13489..4c384e0 100644
--- a/javatests/com/google/gerrit/server/schema/AllProjectsCreatorTest.java
+++ b/javatests/com/google/gerrit/server/schema/AllProjectsCreatorTest.java
@@ -21,6 +21,7 @@
import static com.google.gerrit.server.schema.testing.AllProjectsCreatorTestUtil.getAllProjectsWithoutDefaultAcls;
import static com.google.gerrit.server.schema.testing.AllProjectsCreatorTestUtil.getDefaultAllProjectsWithAllDefaultSections;
import static com.google.gerrit.server.schema.testing.AllProjectsCreatorTestUtil.readAllProjectsConfig;
+import static com.google.gerrit.truth.ConfigSubject.assertThat;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.common.data.GroupReference;
@@ -126,7 +127,7 @@
allProjectsCreator.create(allProjectsInput);
Config config = readAllProjectsConfig(repoManager, allProjectsName);
- assertThat(config.getString("project", null, "description")).isEqualTo(testDescription);
+ assertThat(config).stringValue("project", null, "description").isEqualTo(testDescription);
}
@Test
@@ -142,7 +143,7 @@
allProjectsCreator.create(allProjectsInput);
Config config = readAllProjectsConfig(repoManager, allProjectsName);
- assertThat(config.getBoolean("submit", null, "rejectEmptyCommit", false)).isTrue();
+ assertThat(config).booleanValue("submit", null, "rejectEmptyCommit", false).isTrue();
}
@Test