Test exception handling of CodeOwnersPluginConfigValidator

This increases the test coverage for CodeOwnersPluginConfigValidator
from 87.7% to 100%.

Signed-off-by: Edwin Kempin <ekempin@google.com>
Change-Id: Ieda3f492bf0930cea7606eb0d94a643d82409e89
diff --git a/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/CodeOwnersPluginConfigValidatorIT.java b/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/CodeOwnersPluginConfigValidatorIT.java
index 9edbece..fbaea56 100644
--- a/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/CodeOwnersPluginConfigValidatorIT.java
+++ b/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/CodeOwnersPluginConfigValidatorIT.java
@@ -22,6 +22,7 @@
 import static com.google.gerrit.testing.GerritJUnit.assertThrows;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.gerrit.acceptance.GitUtil;
 import com.google.gerrit.acceptance.PushOneCommit;
@@ -30,6 +31,7 @@
 import com.google.gerrit.extensions.api.changes.RebaseInput;
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.git.ObjectIds;
 import com.google.gerrit.plugins.codeowners.acceptance.AbstractCodeOwnersIT;
 import com.google.gerrit.plugins.codeowners.backend.CodeOwnerBackendId;
 import com.google.gerrit.plugins.codeowners.backend.FallbackCodeOwners;
@@ -53,6 +55,10 @@
 
 /**
  * Tests for {@code com.google.gerrit.plugins.codeowners.config.CodeOwnersPluginConfigValidator}.
+ *
+ * <p>Unit tests for {@code
+ * com.google.gerrit.plugins.codeowners.config.CodeOwnersPluginConfigValidator} are contained in
+ * {@code com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginConfigValidatorTest}.
  */
 public class CodeOwnersPluginConfigValidatorIT extends AbstractCodeOwnersIT {
   private CodeOwnersPluginConfiguration codeOwnersPluginConfiguration;
@@ -661,6 +667,33 @@
                 project, RefNames.REFS_CONFIG));
   }
 
+  @Test
+  public void validatorForProjectConfigIsInvokedBeforeCodeOwnersConfigValidator() throws Exception {
+    fetchRefsMetaConfig();
+    Config cfg = new Config();
+    cfg.setEnum(
+        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
+        /* subsection= */ null,
+        GeneralConfig.KEY_FALLBACK_CODE_OWNERS,
+        FallbackCodeOwners.ALL_USERS);
+    PushOneCommit push =
+        pushFactory.create(
+            admin.newIdent(),
+            testRepo,
+            "Change 1",
+            ImmutableMap.of("code-owners.config", cfg.toText(), "project.config", "INVALID"));
+    PushOneCommit.Result r = push.to("refs/for/" + RefNames.REFS_CONFIG);
+
+    // The invalid project.config is rejected by the project config validator in Gerrit core before
+    // CodeOwnersPluginConfigValidator is invoked (if CodeOwnersPluginConfigValidator would be
+    // invoked first it would fail with a ConfigInvalidException and the message would be "internal
+    // error").
+    r.assertMessage(
+        String.format(
+            "commit %s: invalid project configuration",
+            ObjectIds.abbreviateName(r.getCommit(), testRepo.getRevWalk().getObjectReader())));
+  }
+
   private void fetchRefsMetaConfig() throws Exception {
     fetch(testRepo, RefNames.REFS_CONFIG + ":" + RefNames.REFS_CONFIG);
     testRepo.reset(RefNames.REFS_CONFIG);
diff --git a/javatests/com/google/gerrit/plugins/codeowners/backend/config/CodeOwnersPluginConfigValidatorTest.java b/javatests/com/google/gerrit/plugins/codeowners/backend/config/CodeOwnersPluginConfigValidatorTest.java
new file mode 100644
index 0000000..e05323c
--- /dev/null
+++ b/javatests/com/google/gerrit/plugins/codeowners/backend/config/CodeOwnersPluginConfigValidatorTest.java
@@ -0,0 +1,80 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.plugins.codeowners.backend.config;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.gerrit.server.project.ProjectCache.illegalState;
+import static com.google.gerrit.testing.GerritJUnit.assertThrows;
+
+import com.google.gerrit.entities.RefNames;
+import com.google.gerrit.plugins.codeowners.acceptance.AbstractCodeOwnersTest;
+import com.google.gerrit.plugins.codeowners.backend.FallbackCodeOwners;
+import com.google.gerrit.server.events.CommitReceivedEvent;
+import com.google.gerrit.server.git.validators.CommitValidationException;
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests for {@link CodeOwnersPluginConfigValidator}.
+ *
+ * <p>Integration tests for {@link CodeOwnersPluginConfigValidator} are contained in {@code
+ * com.google.gerrit.plugins.codeowners.acceptance.api.CodeOwnersPluginConfigValidatorIT}.
+ */
+public class CodeOwnersPluginConfigValidatorTest extends AbstractCodeOwnersTest {
+  private CodeOwnersPluginConfigValidator codeOwnersPluginConfigValidator;
+
+  @Before
+  public void setUpCodeOwnersPlugin() throws Exception {
+    codeOwnersPluginConfigValidator =
+        plugin.getSysInjector().getInstance(CodeOwnersPluginConfigValidator.class);
+  }
+
+  @Test
+  public void failsOnInvalidProjectConfig() throws Exception {
+    Config cfg = new Config();
+    cfg.setEnum(
+        CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
+        /* subsection= */ null,
+        GeneralConfig.KEY_FALLBACK_CODE_OWNERS,
+        FallbackCodeOwners.ALL_USERS);
+    RevCommit commit =
+        testRepo
+            .commit()
+            .add("code-owners.config", cfg.toText())
+            .add("project.config", "INVALID")
+            .create();
+    CommitReceivedEvent receiveEvent = new CommitReceivedEvent();
+    receiveEvent.project =
+        projectCache.get(project).orElseThrow(illegalState(project)).getProject();
+    receiveEvent.refName = RefNames.REFS_CONFIG;
+    receiveEvent.commit = commit;
+    receiveEvent.revWalk = testRepo.getRevWalk();
+    receiveEvent.repoConfig = new Config();
+    CommitValidationException exception =
+        assertThrows(
+            CommitValidationException.class,
+            () -> codeOwnersPluginConfigValidator.onCommitReceived(receiveEvent));
+    assertThat(exception)
+        .hasMessageThat()
+        .isEqualTo(
+            String.format(
+                "failed to validate file code-owners.config for revision %s in ref %s of project %s",
+                commit.getName(), RefNames.REFS_CONFIG, project));
+    assertThat(exception).hasCauseThat().isInstanceOf(ConfigInvalidException.class);
+  }
+}