Fail with ConfigInvalidException if checker config contains invalid blocking conditions
If in a checker config file the blocking conditions contain a value
that cannot be resolved to a BlockingCondition enum we failed with an
IllegalArgumentException, but since this is an invalid config it's
better to throw ConfigInvalidException.
Signed-off-by: Edwin Kempin <ekempin@google.com>
Change-Id: If1b868d8b1f9288c2b94407a2556c8dce03e9b30
diff --git a/java/com/google/gerrit/plugins/checks/acceptance/testsuite/CheckerOperationsImpl.java b/java/com/google/gerrit/plugins/checks/acceptance/testsuite/CheckerOperationsImpl.java
index dc1fe68..34c5ad3 100644
--- a/java/com/google/gerrit/plugins/checks/acceptance/testsuite/CheckerOperationsImpl.java
+++ b/java/com/google/gerrit/plugins/checks/acceptance/testsuite/CheckerOperationsImpl.java
@@ -42,11 +42,15 @@
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.BlobBasedConfig;
+import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Ref;
@@ -246,6 +250,24 @@
}
}
+ if (testCheckerUpdate.forceInvalidBlockingCondition()) {
+ try (Repository repo = repoManager.openRepository(allProjectsName)) {
+ TestRepository<Repository> testRepo = new TestRepository<>(repo);
+ Config checkerConfig =
+ readConfig(testRepo, checkerUuid.toRefName(), CheckerConfig.CHECKER_CONFIG_FILE);
+ List<String> blocking =
+ new ArrayList<>(
+ Arrays.asList(checkerConfig.getStringList("checker", null, "blocking")));
+ blocking.add("invalid");
+ checkerConfig.setStringList("checker", null, "blocking", blocking);
+ testRepo
+ .branch(checkerUuid.toRefName())
+ .commit()
+ .add(CheckerConfig.CHECKER_CONFIG_FILE, checkerConfig.toText())
+ .create();
+ }
+ }
+
if (testCheckerUpdate.deleteRef()) {
try (Repository repo = repoManager.openRepository(allProjectsName)) {
RefUpdate ru =
@@ -267,5 +289,11 @@
checkerUpdate.query().ifPresent(builder::setQuery);
return builder.build();
}
+
+ private Config readConfig(TestRepository<?> testRepo, String ref, String fileName)
+ throws Exception {
+ Repository repo = testRepo.getRepository();
+ return new BlobBasedConfig(null, repo, repo.resolve(ref), fileName);
+ }
}
}
diff --git a/java/com/google/gerrit/plugins/checks/acceptance/testsuite/TestCheckerUpdate.java b/java/com/google/gerrit/plugins/checks/acceptance/testsuite/TestCheckerUpdate.java
index 8de1eb6..76d41c0 100644
--- a/java/com/google/gerrit/plugins/checks/acceptance/testsuite/TestCheckerUpdate.java
+++ b/java/com/google/gerrit/plugins/checks/acceptance/testsuite/TestCheckerUpdate.java
@@ -45,6 +45,8 @@
public abstract boolean forceInvalidConfig();
+ public abstract boolean forceInvalidBlockingCondition();
+
public abstract boolean deleteRef();
abstract ThrowingConsumer<TestCheckerUpdate> checkerUpdater();
@@ -53,6 +55,7 @@
return new AutoValue_TestCheckerUpdate.Builder()
.checkerUpdater(checkerUpdater)
.forceInvalidConfig(false)
+ .forceInvalidBlockingCondition(false)
.deleteRef(false);
}
@@ -91,6 +94,12 @@
abstract Builder forceInvalidConfig(boolean forceInvalidConfig);
+ public Builder forceInvalidBlockingCondition() {
+ return forceInvalidBlockingCondition(true);
+ }
+
+ abstract Builder forceInvalidBlockingCondition(boolean forceInvalidBlockingCondition);
+
public Builder deleteRef() {
return deleteRef(true);
}
diff --git a/java/com/google/gerrit/plugins/checks/db/CheckerConfigEntry.java b/java/com/google/gerrit/plugins/checks/db/CheckerConfigEntry.java
index a4bb1ca..d1d49ef 100644
--- a/java/com/google/gerrit/plugins/checks/db/CheckerConfigEntry.java
+++ b/java/com/google/gerrit/plugins/checks/db/CheckerConfigEntry.java
@@ -15,8 +15,6 @@
package com.google.gerrit.plugins.checks.db;
import static com.google.common.collect.ImmutableList.toImmutableList;
-import static com.google.common.collect.ImmutableSortedSet.toImmutableSortedSet;
-import static java.util.Comparator.naturalOrder;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
@@ -31,7 +29,6 @@
import com.google.gerrit.plugins.checks.api.CheckerStatus;
import com.google.gerrit.reviewdb.client.Project;
import java.text.MessageFormat;
-import java.util.Arrays;
import java.util.Locale;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.internal.JGitText;
@@ -251,7 +248,8 @@
BLOCKING_CONDITIONS("blocking") {
@Override
- void readFromConfig(CheckerUuid checkerUuid, Checker.Builder checker, Config config) {
+ void readFromConfig(CheckerUuid checkerUuid, Checker.Builder checker, Config config)
+ throws ConfigInvalidException {
checker.setBlockingConditions(
getEnumSet(config, SECTION_NAME, null, super.keyName, BlockingCondition.values()));
}
@@ -301,14 +299,18 @@
};
private static <T extends Enum<T>> ImmutableSortedSet<T> getEnumSet(
- Config config, String section, @Nullable String subsection, String name, T[] all) {
- return Arrays.stream(config.getStringList(section, subsection, name))
- .map(v -> resolveEnum(section, subsection, name, v, all))
- .collect(toImmutableSortedSet(naturalOrder()));
+ Config config, String section, @Nullable String subsection, String name, T[] all)
+ throws ConfigInvalidException {
+ ImmutableSortedSet.Builder<T> enumBuilder = ImmutableSortedSet.naturalOrder();
+ for (String value : config.getStringList(section, subsection, name)) {
+ enumBuilder.add(resolveEnum(section, subsection, name, value, all));
+ }
+ return enumBuilder.build();
}
private static <T extends Enum<T>> T resolveEnum(
- String section, @Nullable String subsection, String name, String value, T[] all) {
+ String section, @Nullable String subsection, String name, String value, T[] all)
+ throws ConfigInvalidException {
// Match some resolution semantics of DefaultTypedConfigGetter#getEnum.
// TODO(dborowitz): Sure would be nice if Config exposed this logic (or getEnumList) so we
// didn't have to replicate it.
@@ -319,11 +321,11 @@
}
}
if (subsection != null) {
- throw new IllegalArgumentException(
+ throw new ConfigInvalidException(
MessageFormat.format(
JGitText.get().enumValueNotSupported3, section, subsection, name, value));
}
- throw new IllegalArgumentException(
+ throw new ConfigInvalidException(
MessageFormat.format(JGitText.get().enumValueNotSupported2, section, name, value));
}
diff --git a/javatests/com/google/gerrit/plugins/checks/acceptance/api/GetCheckerIT.java b/javatests/com/google/gerrit/plugins/checks/acceptance/api/GetCheckerIT.java
index 32f4649..2cb2ec8 100644
--- a/javatests/com/google/gerrit/plugins/checks/acceptance/api/GetCheckerIT.java
+++ b/javatests/com/google/gerrit/plugins/checks/acceptance/api/GetCheckerIT.java
@@ -212,6 +212,16 @@
}
@Test
+ public void getCheckerWithInvalidBlockingConditionFails() throws Exception {
+ CheckerUuid checkerUuid = checkerOperations.newChecker().create();
+ checkerOperations.checker(checkerUuid).forUpdate().forceInvalidBlockingCondition().update();
+
+ exception.expect(RestApiException.class);
+ exception.expectMessage("Cannot retrieve checker " + checkerUuid);
+ getCheckerInfo(checkerUuid);
+ }
+
+ @Test
public void getCheckerByNameFails() throws Exception {
String name = "my-checker";
checkerOperations.newChecker().name(name).create();
diff --git a/javatests/com/google/gerrit/plugins/checks/acceptance/api/ListCheckersIT.java b/javatests/com/google/gerrit/plugins/checks/acceptance/api/ListCheckersIT.java
index 33d5733..ffe26fc 100644
--- a/javatests/com/google/gerrit/plugins/checks/acceptance/api/ListCheckersIT.java
+++ b/javatests/com/google/gerrit/plugins/checks/acceptance/api/ListCheckersIT.java
@@ -87,10 +87,15 @@
@Test
public void listIgnoresInvalidCheckers() throws Exception {
- CheckerUuid checkerUuid =
- checkerOperations.newChecker().name("checker-with-name-only").create();
- CheckerUuid invalidCheckerUuid = checkerOperations.newChecker().create();
- checkerOperations.checker(invalidCheckerUuid).forUpdate().forceInvalidConfig().update();
+ CheckerUuid checkerUuid = checkerOperations.newChecker().create();
+ CheckerUuid invalidCheckerUuid1 = checkerOperations.newChecker().create();
+ CheckerUuid invalidCheckerUuid2 = checkerOperations.newChecker().create();
+ checkerOperations.checker(invalidCheckerUuid1).forUpdate().forceInvalidConfig().update();
+ checkerOperations
+ .checker(invalidCheckerUuid2)
+ .forUpdate()
+ .forceInvalidBlockingCondition()
+ .update();
List<CheckerInfo> allCheckers = checkersApi.all();
assertThat(allCheckers).containsExactly(checkerOperations.checker(checkerUuid).asInfo());
diff --git a/javatests/com/google/gerrit/plugins/checks/acceptance/testsuite/CheckerOperationsImplTest.java b/javatests/com/google/gerrit/plugins/checks/acceptance/testsuite/CheckerOperationsImplTest.java
index 4060c82..b282e94 100644
--- a/javatests/com/google/gerrit/plugins/checks/acceptance/testsuite/CheckerOperationsImplTest.java
+++ b/javatests/com/google/gerrit/plugins/checks/acceptance/testsuite/CheckerOperationsImplTest.java
@@ -513,6 +513,21 @@
}
@Test
+ public void blockingConditionsCanBeMadeInvalid() throws Exception {
+ CheckerUuid checkerUuid = checkerOperations.newChecker().create();
+
+ checkerOperations.checker(checkerUuid).forUpdate().forceInvalidBlockingCondition().update();
+
+ try {
+ checkers.getChecker(checkerUuid);
+ assert_().fail("expected ConfigInvalidException");
+ } catch (ConfigInvalidException e) {
+ // expected
+ assertThat(e.getMessage()).contains("Invalid value: checker.blocking");
+ }
+ }
+
+ @Test
public void refCanBeDeleted() throws Exception {
CheckerUuid checkerUuid = checkerOperations.newChecker().create();