Use BaseConfig instead of raw PluginConfig.

* Pass to the Config class more Gerrit environment variables,
  including AccountCache, PatchListCache, Emails,
  to have more environment-dependent interpretation
  of config key values in the future.
* Use BaseConfig in Config instead of raw PluginConfig
  to allow future extension with more dynamic key values.
* Simplify Checker methods; remove redundant exception specifications.

Change-Id: I50b274aa7220f566288194a8fd219336536f0ac8
diff --git a/src/main/java/com/googlesource/gerrit/plugins/findowners/Action.java b/src/main/java/com/googlesource/gerrit/plugins/findowners/Action.java
index c97b9f8..0e80906 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/findowners/Action.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/findowners/Action.java
@@ -33,6 +33,7 @@
 import com.google.gerrit.server.change.RevisionResource;
 import com.google.gerrit.server.config.PluginConfigFactory;
 import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.patch.PatchListCache;
 import com.google.gerrit.server.permissions.PermissionBackend;
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.project.ProjectState;
@@ -75,6 +76,7 @@
       Provider<CurrentUser> userProvider,
       ChangeData.Factory changeDataFactory,
       AccountCache accountCache,
+      PatchListCache patchListCache,
       Emails emails,
       GitRepositoryManager repoManager,
       ProjectCache projectCache) {
@@ -85,7 +87,7 @@
     this.emails = emails;
     this.repoManager = repoManager;
     this.projectCache = projectCache;
-    this.config = new Config(configFactory);
+    this.config = new Config(configFactory, null, accountCache, patchListCache, emails);
   }
 
   private String getUserName() {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/findowners/BaseConfig.java b/src/main/java/com/googlesource/gerrit/plugins/findowners/BaseConfig.java
new file mode 100644
index 0000000..a390bf2
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/findowners/BaseConfig.java
@@ -0,0 +1,68 @@
+// 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.googlesource.gerrit.plugins.findowners;
+
+import com.google.gerrit.server.config.PluginConfig;
+
+/**
+ * BaseConfig wraps Gerrit PluginConfig for find-owners Config.
+ *
+ * <p>This base class provides a subset of PluginConfig methods for find-owners Config. It could be
+ * extended in the future to provide more dynamic evaluation of key values. Its contructor keeps and
+ * delegates all methods to a PluginConfig.
+ */
+class BaseConfig {
+  protected final String name; // name of this plugin
+  protected final PluginConfig config; // wrapped PluginConfig
+
+  public BaseConfig(String name, PluginConfig config) {
+    this.name = name;
+    this.config = config;
+  }
+
+  // Return the uninterpreted string value of a key.
+  public String getRawString(String name) {
+    return config.getString(name);
+  }
+
+  // Return the uninterpreted string value of a key with default value.
+  public String getRawString(String name, String defaultValue) {
+    return config.getString(name, defaultValue);
+  }
+
+  public String getString(String name) {
+    return config.getString(name);
+  }
+
+  public String getString(String name, String defaultValue) {
+    return config.getString(name, defaultValue);
+  }
+
+  public int getInt(String name, int defaultValue) {
+    return config.getInt(name, defaultValue);
+  }
+
+  public boolean getBoolean(String name, boolean defaultValue) {
+    return config.getBoolean(name, defaultValue);
+  }
+
+  public <T extends Enum<?>> T getEnum(String name, T defaultValue) {
+    return config.getEnum(name, defaultValue);
+  }
+
+  public <T extends Enum<?>> T getEnum(T[] all, String name, T defaultValue) {
+    return config.getEnum(all, name, defaultValue);
+  }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/findowners/Checker.java b/src/main/java/com/googlesource/gerrit/plugins/findowners/Checker.java
index 0004bf2..53bf34d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/findowners/Checker.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/findowners/Checker.java
@@ -22,8 +22,10 @@
 import com.google.gerrit.server.account.Emails;
 import com.google.gerrit.server.config.PluginConfigFactory;
 import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.patch.PatchListCache;
 import com.google.gerrit.server.project.ProjectState;
 import com.google.gerrit.server.query.change.ChangeData;
+import com.google.gerrit.server.rules.PrologEnvironment;
 import com.google.gerrit.server.rules.StoredValues;
 import com.googlecode.prolog_cafe.lang.Prolog;
 import java.util.HashMap;
@@ -39,28 +41,34 @@
   private static final String EXEMPT_MESSAGE1 = "Exempt-From-Owner-Approval:";
   private static final String EXEMPT_MESSAGE2 = "Exempted-From-Owner-Approval:";
 
+  private final AccountCache accountCache;
   private final GitRepositoryManager repoManager;
+  private final Emails emails;
   private final Config config;
   private final ProjectState projectState; // could be null when used by FindOwnersIT
   private final ChangeData changeData;
   private int minVoteLevel;
 
   Checker(
+      AccountCache accountCache,
+      PatchListCache patchListCache,
       GitRepositoryManager repoManager,
+      Emails emails,
       PluginConfigFactory configFactory,
       ProjectState projectState,
       ChangeData changeData,
       int v) {
+    this.accountCache = accountCache;
     this.repoManager = repoManager;
+    this.emails = emails;
     this.projectState = projectState;
     this.changeData = changeData;
-    this.config = new Config(configFactory);
+    this.config = new Config(configFactory, null, accountCache, patchListCache, emails);
     minVoteLevel = v;
   }
 
   /** Returns a map from reviewer email to vote value. */
-  Map<String, Integer> getVotes(AccountCache accountCache, ChangeData changeData)
-      throws StorageException {
+  Map<String, Integer> getVotes(ChangeData changeData) {
     Map<String, Integer> map = new HashMap<>();
     for (PatchSetApproval p : changeData.currentApprovals()) {
       // Only collect non-zero Code-Review votes.
@@ -110,12 +118,12 @@
   }
 
   /** Returns 1 if owner approval is found, -1 if missing, 0 if unneeded. */
-  int findApproval(AccountCache accountCache, OwnersDb db) throws StorageException {
+  int findApproval(OwnersDb db) {
     Map<String, Set<String>> file2Owners = db.findOwners(changeData.currentFilePaths());
     if (file2Owners.isEmpty()) { // do not need owner approval
       return 0;
     }
-    Map<String, Integer> votes = getVotes(accountCache, changeData);
+    Map<String, Integer> votes = getVotes(changeData);
     for (Set<String> owners : file2Owners.values()) {
       if (!findOwnersInVotes(owners, votes)) {
         return -1;
@@ -129,15 +137,18 @@
     ChangeData changeData = null;
     try {
       changeData = StoredValues.CHANGE_DATA.get(engine);
+      PrologEnvironment env = (PrologEnvironment) engine.control;
       Checker checker =
           new Checker(
+              StoredValues.ACCOUNT_CACHE.get(engine),
+              env.getArgs().getPatchListCache(),
               StoredValues.REPO_MANAGER.get(engine),
+              StoredValues.EMAILS.get(engine),
               StoredValues.PLUGIN_CONFIG_FACTORY.get(engine),
               StoredValues.PROJECT_STATE.get(engine),
               changeData,
               minVoteLevel);
-      return checker.findApproval(
-          StoredValues.ACCOUNT_CACHE.get(engine), StoredValues.EMAILS.get(engine));
+      return checker.findApproval();
     } catch (StorageException e) {
       logger.atSevere().withCause(e).log("Exception for %s ", Config.getChangeId(changeData));
       return 0; // owner approval may or may not be required.
@@ -145,7 +156,7 @@
   }
 
   /** Returns 1 if owner approval is found, -1 if missing, 0 if unneeded. */
-  int findApproval(AccountCache accountCache, Emails emails) throws StorageException {
+  int findApproval() {
     if (isExemptFromOwnerApproval(changeData)) {
       return 0;
     }
@@ -168,11 +179,11 @@
       minVoteLevel = config.getMinOwnerVoteLevel(projectState, changeData);
     }
     logger.atFiner().log("findApproval db key = %s", db.key);
-    return findApproval(accountCache, db);
+    return findApproval(db);
   }
 
   /** Returns true if exempt from owner approval. */
-  static boolean isExemptFromOwnerApproval(ChangeData changeData) throws StorageException {
+  static boolean isExemptFromOwnerApproval(ChangeData changeData) {
     try {
       String message = changeData.commitMessage();
       if (message.contains(EXEMPT_MESSAGE1) || message.contains(EXEMPT_MESSAGE2)) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/findowners/Config.java b/src/main/java/com/googlesource/gerrit/plugins/findowners/Config.java
index 6a35190..24402e8 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/findowners/Config.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/findowners/Config.java
@@ -17,8 +17,11 @@
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.flogger.FluentLogger;
 import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.server.account.AccountCache;
+import com.google.gerrit.server.account.Emails;
 import com.google.gerrit.server.config.PluginConfig;
 import com.google.gerrit.server.config.PluginConfigFactory;
+import com.google.gerrit.server.patch.PatchListCache;
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.project.ProjectState;
 import com.google.gerrit.server.query.change.ChangeData;
@@ -48,10 +51,10 @@
   private final PluginConfigFactory configFactory;
 
   // Each call to API entry point creates one new Config and parses gerrit.config.
-  private final PluginConfig gerritConfig;
+  private final BaseConfig gerritConfig;
 
   // Each Config has a cache of project.config, with projectName:changeId key.
-  private final Map<String, PluginConfig> projectConfigMap;
+  private final Map<String, BaseConfig> projectConfigMap;
 
   // Global/plugin config parameters.
   private boolean addDebugMsg = false;
@@ -60,27 +63,35 @@
   private int maxCacheSize = 1000;
   private boolean reportSyntaxError = false;
 
+  // Gerrit server objects to set up JS initcode for JSEConfig.
+  private final AccountCache accountCache;
+  private final PatchListCache patchListCache;
+  private final Emails emails;
+
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
 
-  Config(PluginConfigFactory configFactory) {
-    // Called by Action() and Checker.findApproval, through Prolog submit filter.
-    this(configFactory, null);
-  }
-
-  @VisibleForTesting
-  Config(PluginConfig rawConfig) {
-    this(null, rawConfig);
-  }
-
-  Config(PluginConfigFactory configFactory, PluginConfig config) {
+  Config(
+      PluginConfigFactory configFactory, // null when called from unit tests
+      PluginConfig config, // null when called by Action and Checker
+      AccountCache accountCache,
+      PatchListCache patchListCache,
+      Emails emails) {
     this.configFactory = configFactory;
-    this.projectConfigMap = new HashMap<>();
+    this.accountCache = accountCache;
+    this.patchListCache = patchListCache;
+    this.emails = emails;
+    projectConfigMap = new HashMap<>();
     if (configFactory == null && config == null) { // When called from integration tests.
-      this.gerritConfig = config;
+      gerritConfig = null;
       return;
     }
-    this.gerritConfig = config == null ? configFactory.getFromGerritConfig(PLUGIN_NAME) : config;
-    // Get config variables from the plugin section of gerrit.config.
+    if (config == null) {
+      config = configFactory.getFromGerritConfig(PLUGIN_NAME);
+    }
+    // Get config variables from the plugin section of gerrit.config
+    // It could use JS in value expressions, if useJSE key value is true
+    // and JSEPluginConfig is available.
+    gerritConfig = newConfig(PLUGIN_NAME, config, null, null, null);
     addDebugMsg = gerritConfig.getBoolean(ADD_DEBUG_MSG, false);
     minOwnerVoteLevel = gerritConfig.getInt(MIN_OWNER_VOTE_LEVEL, 1);
     maxCacheAge = gerritConfig.getInt(MAX_CACHE_AGE, 0);
@@ -88,6 +99,36 @@
     reportSyntaxError = gerritConfig.getBoolean(REPORT_SYNTAX_ERROR, false);
   }
 
+  AccountCache accountCache() {
+    return accountCache;
+  }
+
+  Emails emails() {
+    return emails;
+  }
+
+  PatchListCache patchListCache() {
+    return patchListCache;
+  }
+
+  private static BaseConfig newConfig(
+      String name, PluginConfig cfg, Project project, ProjectState state, ChangeData changeData) {
+    // This function is called
+    // (1) per Config (global gerrit.config), when Action or Checker API is called,
+    //     with null project, state, and changeData.
+    // (2) per ProjectState and ChangeData, for project.config, when getProjectConfig is called.
+    //     with null project and non-null state and changeData.
+    // (3) per Project, for project.config, by OwnersValidator,
+    //     with non-null project and null state and changeData.
+    // Now only BaseConfig is returned.
+    // In the future, other child class of BaseConfig could be returned,
+    // depending on project, state, and changeData..
+    if (changeData != null && state == null && project == null) {
+      logger.atSevere().log("Unexpected null pointer for change %s", getChangeId(changeData));
+    }
+    return new BaseConfig(name, cfg);
+  }
+
   boolean getAddDebugMsg() {
     return addDebugMsg; // defined globally, not per-project
   }
@@ -143,6 +184,12 @@
     return reportSyntaxError;
   }
 
+  static String getProjectName(ProjectState state, Project project) {
+    return state != null
+        ? state.getProject().getName()
+        : (project != null ? project.getName() : "(unknown project)");
+  }
+
   static String getChangeId(ChangeData data) {
     return data == null ? "(unknown change)" : ("c/" + data.getId().get());
   }
@@ -152,20 +199,32 @@
   }
 
   // This is per ProjectState and ChangeData.
-  private PluginConfig getProjectConfig(ProjectState state, ChangeData data) {
+  BaseConfig getProjectConfig(ProjectState state, ChangeData data) {
     // A new Config object is created for every call to Action or Checker.
-    // So it is okay to reuse a PluginConfig per (ProjectState:ChangeData).
+    // So it is okay to reuse a BaseConfig per (ProjectState:ChangeData).
     // ProjectState parameter must not be null.
-    // The data parameter could be used in the future to generate change
-    // dependent PluginConfig.
+    // When the ChangeData parameter is null, the BaseConfig is created
+    // with a dummy CL info for the JS expression evaluator.
     String key = state.getName() + ":" + getChangeId(data);
     return projectConfigMap.computeIfAbsent(
-        key, (String k) -> configFactory.getFromProjectConfigWithInheritance(state, PLUGIN_NAME));
+        key,
+        (String k) ->
+            newConfig(
+                PLUGIN_NAME,
+                configFactory.getFromProjectConfigWithInheritance(state, PLUGIN_NAME),
+                null,
+                state,
+                data));
   }
 
   // Used by OwnersValidator and tests, not cached.
-  PluginConfig getProjectConfig(Project project) throws NoSuchProjectException {
-    return configFactory.getFromProjectConfigWithInheritance(project.getNameKey(), PLUGIN_NAME);
+  BaseConfig getProjectConfig(Project project) throws NoSuchProjectException {
+    return newConfig(
+        PLUGIN_NAME,
+        configFactory.getFromProjectConfigWithInheritance(project.getNameKey(), PLUGIN_NAME),
+        project,
+        null,
+        null);
   }
 
   String getOwnersFileName() {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/findowners/GetOwners.java b/src/main/java/com/googlesource/gerrit/plugins/findowners/GetOwners.java
index ce3fdef..b786ecc 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/findowners/GetOwners.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/findowners/GetOwners.java
@@ -25,6 +25,7 @@
 import com.google.gerrit.server.change.ChangeResource;
 import com.google.gerrit.server.config.PluginConfigFactory;
 import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.patch.PatchListCache;
 import com.google.gerrit.server.permissions.PermissionBackend;
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.query.change.ChangeData;
@@ -58,6 +59,7 @@
       Provider<CurrentUser> userProvider,
       ChangeData.Factory dataFactory,
       AccountCache accountCache,
+      PatchListCache patchListCache,
       Emails emails,
       GitRepositoryManager repoManager,
       ProjectCache projectCache) {
@@ -68,6 +70,7 @@
             userProvider,
             dataFactory,
             accountCache,
+            patchListCache,
             emails,
             repoManager,
             projectCache);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/findowners/OwnersValidator.java b/src/main/java/com/googlesource/gerrit/plugins/findowners/OwnersValidator.java
index aa69aa9..9ef1893 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/findowners/OwnersValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/findowners/OwnersValidator.java
@@ -25,6 +25,7 @@
 import com.google.gerrit.extensions.registration.DynamicSet;
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.account.Emails;
 import com.google.gerrit.server.config.PluginConfig;
 import com.google.gerrit.server.config.PluginConfigFactory;
@@ -34,6 +35,7 @@
 import com.google.gerrit.server.git.validators.CommitValidationException;
 import com.google.gerrit.server.git.validators.CommitValidationListener;
 import com.google.gerrit.server.git.validators.CommitValidationMessage;
+import com.google.gerrit.server.patch.PatchListCache;
 import com.google.inject.AbstractModule;
 import com.google.inject.Inject;
 import java.io.BufferedReader;
@@ -91,17 +93,33 @@
   private final Emails emails;
 
   @Inject
-  OwnersValidator(PluginConfigFactory cfgFactory, GitRepositoryManager repoManager, Emails emails) {
-    this(new Config(cfgFactory), repoManager, emails);
+  OwnersValidator(
+      PluginConfigFactory cfgFactory,
+      AccountCache accountCache,
+      PatchListCache patchListCache,
+      GitRepositoryManager repoManager,
+      Emails emails) {
+    this(cfgFactory, null, accountCache, patchListCache, repoManager, emails);
   }
 
   @VisibleForTesting
-  OwnersValidator(PluginConfig config, GitRepositoryManager repoManager, Emails emails) {
-    this(new Config(config), repoManager, emails);
+  OwnersValidator(
+      PluginConfig config,
+      AccountCache accountCache,
+      PatchListCache patchListCache,
+      GitRepositoryManager repoManager,
+      Emails emails) {
+    this(null, config, accountCache, patchListCache, repoManager, emails);
   }
 
-  private OwnersValidator(Config config, GitRepositoryManager repoManager, Emails emails) {
-    this.config = config;
+  private OwnersValidator(
+      PluginConfigFactory cfgFactory,
+      PluginConfig config,
+      AccountCache accountCache,
+      PatchListCache patchListCache,
+      GitRepositoryManager repoManager,
+      Emails emails) {
+    this.config = new Config(cfgFactory, config, accountCache, patchListCache, emails);
     this.repoManager = repoManager;
     this.emails = emails;
   }
diff --git a/src/test/java/com/googlesource/gerrit/plugins/findowners/ApiIT.java b/src/test/java/com/googlesource/gerrit/plugins/findowners/ApiIT.java
index ecd1401..7481b06 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/findowners/ApiIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/findowners/ApiIT.java
@@ -115,6 +115,7 @@
             null,
             changeDataFactory,
             accountCache,
+            patchListCache,
             emails,
             repoManager,
             projectCache);
diff --git a/src/test/java/com/googlesource/gerrit/plugins/findowners/BaseConfigTest.java b/src/test/java/com/googlesource/gerrit/plugins/findowners/BaseConfigTest.java
new file mode 100644
index 0000000..ca5ec1f
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/findowners/BaseConfigTest.java
@@ -0,0 +1,70 @@
+// 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.googlesource.gerrit.plugins.findowners;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import com.google.gerrit.server.config.PluginConfig;
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.lib.Config;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class BaseConfigTest {
+
+  private static BaseConfig createConfig(String name, String content)
+      throws ConfigInvalidException {
+    Config cfg = new Config();
+    cfg.fromText(content); // could throw ConfigInvalidException
+    return new BaseConfig(name, new PluginConfig(name, cfg));
+  }
+
+  private static String pluginSection(String name) {
+    return "[plugin \"" + name + "\"]\n";
+  }
+
+  private static void sanityChecks(BaseConfig cfg) throws ConfigInvalidException {
+    assertEquals("string", "1+1", cfg.getString("k1"));
+    assertEquals("string", "'t'+k1", cfg.getString("v1"));
+    assertEquals("int", 2, cfg.getInt("v2", 1));
+    assertNull(cfg.getString("k3"));
+    assertTrue("boolean", cfg.getBoolean("k2", false));
+    assertEquals("string", "1+1", cfg.getRawString("k1"));
+    assertEquals("string", "'t'+k1", cfg.getRawString("v1"));
+    assertEquals("string", "true", cfg.getRawString("k2"));
+    assertEquals("string", "2", cfg.getRawString("v2"));
+  }
+
+  @Test
+  public void sanity() throws ConfigInvalidException {
+    String name = "find-owners";
+    String content0 = pluginSection(name) + "k1=1+1\nk2=true\nv1='t'+k1\nv2=2\n";
+    String content1 = pluginSection("other") + "k3='abc'\n";
+    BaseConfig cfg = createConfig(name, content0 + content1);
+    sanityChecks(cfg);
+    assertFalse("boolean", cfg.getBoolean("useJSE", false));
+    assertTrue("boolean", cfg.getBoolean("useJSE", true));
+    // Config contains useJSE=true, but BaseConfig does not use it.
+    cfg = createConfig(name, content0 + "useJSE=true\n" + content1);
+    sanityChecks(cfg);
+    assertTrue("boolean", cfg.getBoolean("useJSE", false));
+    assertTrue("boolean", cfg.getBoolean("useJSE", true));
+  }
+}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/findowners/FindOwners.java b/src/test/java/com/googlesource/gerrit/plugins/findowners/FindOwners.java
index 872cda4..293ce02 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/findowners/FindOwners.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/findowners/FindOwners.java
@@ -34,6 +34,7 @@
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.reviewdb.client.RefNames;
 import com.google.gerrit.server.account.Emails;
+import com.google.gerrit.server.patch.PatchListCache;
 import com.google.gerrit.server.permissions.PermissionBackend;
 import com.google.inject.Inject;
 import org.eclipse.jgit.lib.ObjectLoader;
@@ -51,13 +52,14 @@
   @Inject protected Emails emails;
   @Inject protected PermissionBackend permissionBackend;
   @Inject protected ProjectOperations projectOperations;
+  @Inject protected PatchListCache patchListCache;
 
   protected static final String PLUGIN_NAME = "find-owners";
   protected Config config;
 
   @Before
   public void setConfig() {
-    config = new Config(pluginConfig);
+    config = new Config(pluginConfig, null, null, null, null);
   }
 
   protected String oneOwnerList(String email) {
@@ -163,6 +165,7 @@
             .to("refs/for/" + REFS_CONFIG);
     commit.assertOkStatus();
     approveSubmit(commit);
+    testRepo = cloneProject(project); // reset the testRepo after cfg change
   }
 
   protected int checkApproval(PushOneCommit.Result r) throws Exception {
@@ -178,8 +181,17 @@
             repoManager,
             r.getChange(),
             1);
-    Checker c = new Checker(repoManager, pluginConfig, null, r.getChange(), 1);
-    return c.findApproval(accountCache, db);
+    Checker c =
+        new Checker(
+            accountCache,
+            patchListCache,
+            repoManager,
+            emails,
+            pluginConfig,
+            null,
+            r.getChange(),
+            1);
+    return c.findApproval(db);
   }
 
   // To simplify test case code, the REST API returned JSON string is filtered to
diff --git a/src/test/java/com/googlesource/gerrit/plugins/findowners/OwnersValidatorIT.java b/src/test/java/com/googlesource/gerrit/plugins/findowners/OwnersValidatorIT.java
index 0eb7df1..8b6b3f2 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/findowners/OwnersValidatorIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/findowners/OwnersValidatorIT.java
@@ -127,7 +127,7 @@
   private static final PluginConfig DISABLED_CONFIG = createDisabledConfig();
 
   private OwnersValidator newOwnersValidator(PluginConfig cfg) {
-    return new OwnersValidator(cfg, repoManager, new MockedEmails());
+    return new OwnersValidator(cfg, accountCache, patchListCache, repoManager, new MockedEmails());
   }
 
   @Test