ProjectOperations: Allow arbitrary updates of project.config
This allows tests to insert invalid entries in the project.config file. Signed-off-by: Edwin Kempin <ekempin@google.com> Change-Id: I01440867b295e843507ca41bcd703af659db32dd
This commit is contained in:
@@ -14,6 +14,7 @@ java_library(
|
||||
"//java/com/google/gerrit/server",
|
||||
"//lib:guava",
|
||||
"//lib:jgit",
|
||||
"//lib:jgit-junit",
|
||||
"//lib/auto:auto-value",
|
||||
"//lib/auto:auto-value-annotations",
|
||||
"//lib/commons:lang",
|
||||
|
||||
@@ -73,5 +73,25 @@ public interface ProjectOperations {
|
||||
* @return a builder to update the check.
|
||||
*/
|
||||
TestProjectUpdate.Builder forUpdate();
|
||||
|
||||
/**
|
||||
* Starts the fluent chain to invalidate a project. The returned builder can be used to specify
|
||||
* how the project should be made invalid. To invalidate the project for real, {@link
|
||||
* TestProjectInvalidation.Builder#invalidate()} must be called.
|
||||
*
|
||||
* <p>Example:
|
||||
*
|
||||
* <pre>
|
||||
* projectOperations.forInvalidation()
|
||||
* .addProjectConfigUpdater(cfg -> cfg.setString("invalidSection", null, "foo", "bar"))
|
||||
* .invalidate();
|
||||
* </pre>
|
||||
*
|
||||
* <p><strong>Note:</strong> The invalidation will fail with an exception if the project to
|
||||
* invalidate doesn't exist.
|
||||
*
|
||||
* @return a builder to invalidate the project
|
||||
*/
|
||||
TestProjectInvalidation.Builder forInvalidation();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ 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.base.Throwables;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gerrit.acceptance.testsuite.project.TestProjectCreation.Builder;
|
||||
@@ -45,6 +46,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import org.apache.commons.lang.RandomStringUtils;
|
||||
import org.eclipse.jgit.errors.ConfigInvalidException;
|
||||
import org.eclipse.jgit.junit.TestRepository;
|
||||
import org.eclipse.jgit.lib.Config;
|
||||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.ObjectLoader;
|
||||
@@ -255,6 +257,48 @@ public class ProjectOperationsImpl implements ProjectOperations {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void setConfig(Config projectConfig) {
|
||||
try (TestRepository<Repository> repo =
|
||||
new TestRepository<>(repoManager.openRepository(nameKey))) {
|
||||
repo.update(
|
||||
RefNames.REFS_CONFIG,
|
||||
repo.commit()
|
||||
.message("Update project.config from test")
|
||||
.parent(getHead(RefNames.REFS_CONFIG))
|
||||
.add(ProjectConfig.PROJECT_CONFIG, projectConfig.toText()));
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException(
|
||||
"updating project.config of project " + nameKey + " failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TestProjectInvalidation.Builder forInvalidation() {
|
||||
return TestProjectInvalidation.builder(this::invalidateProject);
|
||||
}
|
||||
|
||||
private void invalidateProject(TestProjectInvalidation testProjectInvalidation)
|
||||
throws Exception {
|
||||
if (!testProjectInvalidation.projectConfigUpdater().isEmpty()) {
|
||||
Config projectConfig = new Config();
|
||||
projectConfig.fromText(getConfig().toText());
|
||||
testProjectInvalidation.projectConfigUpdater().forEach(c -> c.accept(projectConfig));
|
||||
setConfig(projectConfig);
|
||||
try {
|
||||
projectCache.evict(nameKey);
|
||||
} catch (Exception e) {
|
||||
// Evicting the project from the cache, also triggers a reindex of the project.
|
||||
// The reindex step fails if the project config is invalid. That's fine, since it was our
|
||||
// intention to make the project config invalid. Hence we ignore exceptions that are cause
|
||||
// by an invalid project config here.
|
||||
if (!Throwables.getCausalChain(e).stream()
|
||||
.anyMatch(ConfigInvalidException.class::isInstance)) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static PermissionRule newRule(ProjectConfig project, AccountGroup.UUID groupUUID) {
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
// Copyright (C) 2020 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.acceptance.testsuite.project;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gerrit.acceptance.testsuite.ThrowingConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import org.eclipse.jgit.lib.Config;
|
||||
|
||||
/**
|
||||
* API to invalidate projects in tests.
|
||||
*
|
||||
* <p>This allows to test Gerrit behavior when there is invalid project data in NoteDb (e.g. an
|
||||
* invalid {@code project.config} file).
|
||||
*/
|
||||
@AutoValue
|
||||
public abstract class TestProjectInvalidation {
|
||||
public abstract ImmutableList<Consumer<Config>> projectConfigUpdater();
|
||||
|
||||
abstract ThrowingConsumer<TestProjectInvalidation> projectInvalidator();
|
||||
|
||||
public static Builder builder(ThrowingConsumer<TestProjectInvalidation> projectInvalidator) {
|
||||
return new AutoValue_TestProjectInvalidation.Builder().projectInvalidator(projectInvalidator);
|
||||
}
|
||||
|
||||
@AutoValue.Builder
|
||||
public abstract static class Builder {
|
||||
/**
|
||||
* Adds a consumer that can update the project config.
|
||||
*
|
||||
* <p>This allows tests to set arbitrary values in the project config.
|
||||
*/
|
||||
public Builder addProjectConfigUpdater(Consumer<Config> projectConfigUpdater) {
|
||||
projectConfigUpdaterBuilder().add(projectConfigUpdater);
|
||||
return this;
|
||||
}
|
||||
|
||||
protected abstract ImmutableList.Builder<Consumer<Config>> projectConfigUpdaterBuilder();
|
||||
|
||||
abstract Builder projectInvalidator(
|
||||
ThrowingConsumer<TestProjectInvalidation> projectInvalidator);
|
||||
|
||||
abstract TestProjectInvalidation autoBuild();
|
||||
|
||||
/** Executes the project invalidation as specified. */
|
||||
public void invalidate() {
|
||||
TestProjectInvalidation projectInvalidation = autoBuild();
|
||||
projectInvalidation.projectInvalidator().acceptAndThrowSilently(projectInvalidation);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user