Respect ignoreSelfApproval and add end-to-end test

This commit wires up the ignoreSelfApproval bit with the new rule in
Gerrit core. It thereby removes the respective rule from the plugin
as that was moved to core as well.

This commit adds an end-to-end test that configures behavior on the
API and asserts that changes are or are not submittable. While
implementing the end-to-end test, we removed the
AbstractSimpleSubmitRulesIT and replaced it with a project config
update call.

The new PluginIT contains end-to-end tests for reading and writing
API values and for all rules that can be configured. Smaller fixes
to the logic were made where necessary. This mostly covers the
ability to set labels and comment rules independently of each other.

Change-Id: I8cf73155028f23297193346c18c0bad7da4576fd
diff --git a/BUILD b/BUILD
index 38fcfd6..b4a3fc8 100644
--- a/BUILD
+++ b/BUILD
@@ -1,7 +1,7 @@
 load("//tools/bzl:genrule2.bzl", "genrule2")
 load("//tools/bzl:js.bzl", "polygerrit_plugin")
 load("//tools/bzl:junit.bzl", "junit_tests")
-load("//tools/bzl:plugin.bzl", "gerrit_plugin", "PLUGIN_DEPS", "PLUGIN_TEST_DEPS")
+load("//tools/bzl:plugin.bzl", "PLUGIN_DEPS", "PLUGIN_TEST_DEPS", "gerrit_plugin")
 
 gerrit_plugin(
     name = "simple-submit-rules",
@@ -15,27 +15,13 @@
     resources = glob(["src/main/resources/**/*"]),
 )
 
-ABSTRACT_TEST_BASE = ["src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/AbstractSimpleSubmitRulesIT.java"]
-
-java_library(
-    name = "abstract_test_base",
-    testonly = 1,
-    srcs = ABSTRACT_TEST_BASE,
-    visibility = ["//visibility:public"],
-    deps = PLUGIN_TEST_DEPS + PLUGIN_DEPS + [
-        ":simple-submit-rules__plugin",
-    ],
-)
-
 junit_tests(
     name = "tests",
     srcs = glob(
         ["src/test/java/**/*.java"],
-        exclude = ABSTRACT_TEST_BASE,
     ),
     visibility = ["//visibility:public"],
     deps = PLUGIN_TEST_DEPS + PLUGIN_DEPS + [
-        ":abstract_test_base",
         ":simple-submit-rules__plugin",
     ],
 )
diff --git a/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/BatchModule.java b/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/BatchModule.java
index 3e9d696..76f8385 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/BatchModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/BatchModule.java
@@ -19,14 +19,12 @@
 import com.google.inject.AbstractModule;
 import com.googlesource.gerrit.plugins.simplesubmitrules.config.ConfigTranslator;
 import com.googlesource.gerrit.plugins.simplesubmitrules.rules.NoUnresolvedCommentsRule;
-import com.googlesource.gerrit.plugins.simplesubmitrules.rules.RequireNonAuthorApprovalRule;
 
 /** Rules for the batch programs (offline reindexer) */
 public class BatchModule extends AbstractModule {
   @Override
   protected void configure() {
     bind(ConfigTranslator.class);
-    DynamicSet.bind(binder(), SubmitRule.class).to(RequireNonAuthorApprovalRule.class);
     DynamicSet.bind(binder(), SubmitRule.class).to(NoUnresolvedCommentsRule.class);
   }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/SimpleSubmitRulesConfig.java b/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/SimpleSubmitRulesConfig.java
index 856e71a..ec2c88b 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/SimpleSubmitRulesConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/SimpleSubmitRulesConfig.java
@@ -15,7 +15,6 @@
 package com.googlesource.gerrit.plugins.simplesubmitrules;
 
 public final class SimpleSubmitRulesConfig {
-  public static final String KEY_REQUIRE_NON_AUTHOR_APPROVAL = "nonAuthorApprovalRequired";
   public static final String KEY_BLOCK_IF_UNRESOLVED_COMMENTS = "blockIfUnresolvedComments";
 
   private SimpleSubmitRulesConfig() {}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/api/CommentsRules.java b/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/api/CommentsRules.java
new file mode 100644
index 0000000..363f418
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/api/CommentsRules.java
@@ -0,0 +1,47 @@
+// Copyright (C) 2018 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.simplesubmitrules.api;
+
+import com.google.common.base.MoreObjects;
+import java.util.Objects;
+
+public class CommentsRules {
+  public boolean blockIfUnresolvedComments;
+
+  public CommentsRules(boolean blockIfUnresolvedComments) {
+    this.blockIfUnresolvedComments = blockIfUnresolvedComments;
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(blockIfUnresolvedComments);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof CommentsRules)) {
+      return false;
+    }
+    CommentsRules other = (CommentsRules) o;
+    return blockIfUnresolvedComments == other.blockIfUnresolvedComments;
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("blockIfUnresolvedComments", blockIfUnresolvedComments)
+        .toString();
+  }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/api/LabelDefinition.java b/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/api/LabelDefinition.java
new file mode 100644
index 0000000..3ded3c2
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/api/LabelDefinition.java
@@ -0,0 +1,67 @@
+// Copyright (C) 2018 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.simplesubmitrules.api;
+
+import com.google.common.base.MoreObjects;
+import com.google.gerrit.common.data.LabelFunction;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+
+public class LabelDefinition {
+  public String function;
+  public Boolean ignoreSelfApproval;
+  public Set<String> copyScores;
+
+  public LabelDefinition() {
+    copyScores = new HashSet<>();
+  }
+
+  public LabelDefinition(String function, Boolean ignoreSelfApproval, Set<String> copyScores) {
+    this.function = function;
+    this.ignoreSelfApproval = ignoreSelfApproval;
+    this.copyScores = copyScores;
+  }
+
+  public Optional<LabelFunction> getFunction() {
+    return LabelFunction.parse(function);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(function, ignoreSelfApproval, copyScores);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof LabelDefinition)) {
+      return false;
+    }
+    LabelDefinition other = (LabelDefinition) o;
+    return Objects.equals(function, other.function)
+        && Objects.equals(ignoreSelfApproval, other.ignoreSelfApproval)
+        && Objects.equals(copyScores, other.copyScores);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("function", function)
+        .add("ignoreSelfApproval", ignoreSelfApproval)
+        .add("copyScores", copyScores)
+        .toString();
+  }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/api/SubmitConfig.java b/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/api/SubmitConfig.java
new file mode 100644
index 0000000..a538a57
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/api/SubmitConfig.java
@@ -0,0 +1,58 @@
+// Copyright (C) 2018 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.simplesubmitrules.api;
+
+import com.google.common.base.MoreObjects;
+import com.google.inject.Singleton;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+@Singleton
+public class SubmitConfig {
+  public Map<String, LabelDefinition> labels;
+  public CommentsRules comments;
+
+  public SubmitConfig() {
+    labels = new HashMap<>();
+  }
+
+  public SubmitConfig(Map<String, LabelDefinition> labels, CommentsRules comments) {
+    this.labels = labels;
+    this.comments = comments;
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(labels, comments);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof SubmitConfig)) {
+      return false;
+    }
+    SubmitConfig other = (SubmitConfig) o;
+    return Objects.equals(labels, other.labels) && Objects.equals(comments, other.comments);
+  }
+
+  @Override
+  public String toString() {
+    return MoreObjects.toStringHelper(this)
+        .add("labels", labels)
+        .add("comments", comments)
+        .toString();
+  }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/config/ConfigServlet.java b/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/config/ConfigServlet.java
index 1cf6e88..eae8d61 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/config/ConfigServlet.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/config/ConfigServlet.java
@@ -27,6 +27,7 @@
 import com.google.gerrit.server.project.ProjectResource;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
+import com.googlesource.gerrit.plugins.simplesubmitrules.api.SubmitConfig;
 import java.io.IOException;
 
 /** REST Endpoint to configure labels and our simple submit rules */
diff --git a/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/config/ConfigTranslator.java b/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/config/ConfigTranslator.java
index 6a8ce81..035a2a8 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/config/ConfigTranslator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/config/ConfigTranslator.java
@@ -14,6 +14,7 @@
 
 package com.googlesource.gerrit.plugins.simplesubmitrules.config;
 
+import com.google.gerrit.common.Nullable;
 import com.google.gerrit.common.data.LabelType;
 import com.google.gerrit.common.data.LabelTypes;
 import com.google.gerrit.extensions.annotations.PluginName;
@@ -25,6 +26,9 @@
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import com.googlesource.gerrit.plugins.simplesubmitrules.SimpleSubmitRulesConfig;
+import com.googlesource.gerrit.plugins.simplesubmitrules.api.CommentsRules;
+import com.googlesource.gerrit.plugins.simplesubmitrules.api.LabelDefinition;
+import com.googlesource.gerrit.plugins.simplesubmitrules.api.SubmitConfig;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Map;
@@ -41,8 +45,7 @@
     this.pluginName = pluginName;
   }
 
-  static void extractLabelCopyScores(
-      LabelType labelType, SubmitConfig.LabelDefinition labelDefinition) {
+  static void extractLabelCopyScores(LabelType labelType, LabelDefinition labelDefinition) {
     labelDefinition.copyScores = new HashSet<>();
     if (labelType.isCopyMinScore()) {
       labelDefinition.copyScores.add(ProjectConfig.KEY_COPY_MIN_SCORE);
@@ -65,20 +68,19 @@
     }
   }
 
-  static void applyCopyScoresTo(Collection<String> copyScores, LabelType labelType) {
+  static void applyCopyScoresTo(@Nullable Collection<String> copyScores, LabelType labelType) {
+    if (copyScores == null) {
+      return;
+    }
+
     labelType.setCopyMinScore(copyScores.contains(ProjectConfig.KEY_COPY_MIN_SCORE));
-
     labelType.setCopyMaxScore(copyScores.contains(ProjectConfig.KEY_COPY_MAX_SCORE));
-
     labelType.setCopyAllScoresIfNoChange(
         copyScores.contains(ProjectConfig.KEY_COPY_ALL_SCORES_IF_NO_CHANGE));
-
     labelType.setCopyAllScoresIfNoCodeChange(
         copyScores.contains(ProjectConfig.KEY_COPY_ALL_SCORES_IF_NO_CODE_CHANGE));
-
     labelType.setCopyAllScoresOnMergeFirstParentUpdate(
         copyScores.contains(ProjectConfig.KEY_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE));
-
     labelType.setCopyAllScoresOnTrivialRebase(
         copyScores.contains(ProjectConfig.KEY_COPY_ALL_SCORES_ON_TRIVIAL_REBASE));
   }
@@ -88,8 +90,9 @@
     PluginConfig config =
         pluginConfigFactory.getFromProjectConfigWithInheritance(projectState, pluginName);
 
-    submitConfig.comments.blockIfUnresolvedComments =
-        config.getBoolean(SimpleSubmitRulesConfig.KEY_BLOCK_IF_UNRESOLVED_COMMENTS, false);
+    submitConfig.comments =
+        new CommentsRules(
+            config.getBoolean(SimpleSubmitRulesConfig.KEY_BLOCK_IF_UNRESOLVED_COMMENTS, false));
 
     projectState
         .getLabelTypes()
@@ -108,13 +111,12 @@
     applyLabelsTo(inConfig.labels, projectState.getLabelTypes());
   }
 
-  private static void applyLabelsTo(
-      Map<String, SubmitConfig.LabelDefinition> labels, LabelTypes config)
+  private static void applyLabelsTo(Map<String, LabelDefinition> labels, LabelTypes labelTypes)
       throws BadRequestException {
-    for (Map.Entry<String, SubmitConfig.LabelDefinition> entry : labels.entrySet()) {
+    for (Map.Entry<String, LabelDefinition> entry : labels.entrySet()) {
       String label = entry.getKey();
-      SubmitConfig.LabelDefinition definition = entry.getValue();
-      LabelType labelType = config.byLabel(label);
+      LabelDefinition definition = entry.getValue();
+      LabelType labelType = labelTypes.byLabel(label);
 
       if (labelType == null) {
         throw new BadRequestException(
@@ -122,7 +124,9 @@
       }
 
       definition.getFunction().ifPresent(labelType::setFunction);
-
+      if (definition.ignoreSelfApproval != null) {
+        labelType.setIgnoreSelfApproval(definition.ignoreSelfApproval);
+      }
       applyCopyScoresTo(definition.copyScores, labelType);
     }
   }
@@ -132,15 +136,18 @@
       return;
     }
 
-    SubmitConfig.LabelDefinition labelDefinition = new SubmitConfig.LabelDefinition();
+    LabelDefinition labelDefinition = new LabelDefinition();
     config.labels.put(labelType.getName(), labelDefinition);
 
     labelDefinition.function = labelType.getFunction().getFunctionName();
     extractLabelCopyScores(labelType, labelDefinition);
+    labelDefinition.ignoreSelfApproval = labelType.ignoreSelfApproval();
   }
 
-  private static void applyCommentRulesTo(
-      SubmitConfig.CommentsRules comments, PluginConfig config) {
+  private static void applyCommentRulesTo(@Nullable CommentsRules comments, PluginConfig config) {
+    if (comments == null) {
+      return;
+    }
     config.setBoolean(
         SimpleSubmitRulesConfig.KEY_BLOCK_IF_UNRESOLVED_COMMENTS,
         comments.blockIfUnresolvedComments);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/config/SubmitConfig.java b/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/config/SubmitConfig.java
deleted file mode 100644
index 0d7ae98..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/config/SubmitConfig.java
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (C) 2018 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.simplesubmitrules.config;
-
-import com.google.common.base.MoreObjects;
-import com.google.gerrit.common.data.LabelFunction;
-import com.google.inject.Singleton;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-
-@Singleton
-public class SubmitConfig {
-  public Map<String, SubmitConfig.LabelDefinition> labels = new HashMap<>();
-  public SubmitConfig.CommentsRules comments = new SubmitConfig.CommentsRules();
-
-  @Override
-  public String toString() {
-    return MoreObjects.toStringHelper(this)
-        .add("labels", labels)
-        .add("comments", comments)
-        .toString();
-  }
-
-  static class LabelDefinition {
-    String function;
-    boolean ignoreSelfApproval;
-    Set<String> copyScores;
-
-    Optional<LabelFunction> getFunction() {
-      return LabelFunction.parse(function);
-    }
-
-    @Override
-    public String toString() {
-      return MoreObjects.toStringHelper(this)
-          .add("function", function)
-          .add("ignoreSelfApproval", ignoreSelfApproval)
-          .add("copyScores", copyScores)
-          .toString();
-    }
-  }
-
-  static class CommentsRules {
-    boolean blockIfUnresolvedComments;
-
-    @Override
-    public String toString() {
-      return MoreObjects.toStringHelper(this)
-          .add("blockIfUnresolvedComments", blockIfUnresolvedComments)
-          .toString();
-    }
-  }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/rules/RequireNonAuthorApprovalRule.java b/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/rules/RequireNonAuthorApprovalRule.java
deleted file mode 100644
index b4df629..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/simplesubmitrules/rules/RequireNonAuthorApprovalRule.java
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright (C) 2018 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.simplesubmitrules.rules;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.gerrit.common.data.LabelFunction;
-import com.google.gerrit.common.data.LabelType;
-import com.google.gerrit.common.data.SubmitRecord;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.PatchSetApproval;
-import com.google.gerrit.server.project.ProjectCache;
-import com.google.gerrit.server.project.ProjectConfig;
-import com.google.gerrit.server.project.ProjectState;
-import com.google.gerrit.server.project.SubmitRuleOptions;
-import com.google.gerrit.server.query.change.ChangeData;
-import com.google.gerrit.server.rules.SubmitRule;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.simplesubmitrules.SimpleSubmitRulesConfig;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.stream.Collectors;
-import org.eclipse.jgit.lib.Config;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/** Simple rule: require a non-author approval or block submission */
-@Singleton
-public class RequireNonAuthorApprovalRule implements SubmitRule {
-  private static final Logger log = LoggerFactory.getLogger(RequireNonAuthorApprovalRule.class);
-  private static final String E_UNABLE_TO_FETCH_CHANGE_OWNER = "Unable to fetch the change owner";
-  private static final String E_UNABLE_TO_FETCH_LABELS =
-      "Unable to fetch labels and approvals for the change";
-  private final ProjectCache projectCache;
-
-  @Inject
-  public RequireNonAuthorApprovalRule(ProjectCache projectCache) {
-    this.projectCache = projectCache;
-  }
-
-  @Override
-  public Collection<SubmitRecord> evaluate(ChangeData cd, SubmitRuleOptions options) {
-    ProjectState projectState = projectCache.get(cd.project());
-    Config config = projectState.getConfig(ProjectConfig.PROJECT_CONFIG).getWithInheritance();
-
-    Account.Id owner;
-    try {
-      owner = cd.change().getOwner();
-    } catch (OrmException e) {
-      log.error(E_UNABLE_TO_FETCH_CHANGE_OWNER, e);
-
-      SubmitRecord submitRecord = new SubmitRecord();
-      submitRecord.errorMessage = E_UNABLE_TO_FETCH_CHANGE_OWNER;
-      submitRecord.status = SubmitRecord.Status.RULE_ERROR;
-      return Collections.singletonList(submitRecord);
-    }
-
-    List<LabelType> labelTypes;
-    List<PatchSetApproval> approvals;
-    try {
-      labelTypes = cd.getLabelTypes().getLabelTypes();
-      approvals = cd.currentApprovals();
-    } catch (OrmException e) {
-      log.error(E_UNABLE_TO_FETCH_LABELS, e);
-
-      SubmitRecord submitRecord = new SubmitRecord();
-      submitRecord.errorMessage = E_UNABLE_TO_FETCH_LABELS;
-      submitRecord.status = SubmitRecord.Status.RULE_ERROR;
-
-      return Collections.singletonList(submitRecord);
-    }
-
-    SubmitRecord submitRecord = new SubmitRecord();
-    submitRecord.status = SubmitRecord.Status.OK;
-    submitRecord.labels = new ArrayList<>(labelTypes.size());
-
-    for (LabelType t : labelTypes) {
-      if (!config.getBoolean(
-          t.getName(), SimpleSubmitRulesConfig.KEY_REQUIRE_NON_AUTHOR_APPROVAL, false)) {
-        // The default rules are enough in this case.
-        continue;
-      }
-
-      LabelFunction labelFunction = t.getFunction();
-      if (labelFunction == null) {
-        continue;
-      }
-
-      Collection<PatchSetApproval> approvalsForLabel = getApprovalsForLabel(approvals, t, owner);
-      SubmitRecord.Label label = labelFunction.check(t, approvalsForLabel);
-
-      switch (label.status) {
-        case OK:
-        case MAY:
-          break;
-
-        case NEED:
-        case REJECT:
-        case IMPOSSIBLE:
-          submitRecord.labels.add(label);
-          submitRecord.status = SubmitRecord.Status.NOT_READY;
-          break;
-      }
-    }
-
-    if (submitRecord.labels.isEmpty()) {
-      return Collections.emptyList();
-    }
-
-    return Collections.singletonList(submitRecord);
-  }
-
-  /**
-   * Returns the approvals for a given label, for everyone except from `user`, except if the vote is
-   * negative.
-   */
-  @VisibleForTesting
-  static Collection<PatchSetApproval> getApprovalsForLabel(
-      Collection<PatchSetApproval> approvals, LabelType t, Account.Id user) {
-    return approvals
-        .stream()
-        .filter(input -> input.getValue() < 0 || !input.getAccountId().equals(user))
-        .filter(input -> input.getLabel().equals(t.getLabelId().get()))
-        .collect(Collectors.toList());
-  }
-}
diff --git a/src/main/resources/Documentation/about.md b/src/main/resources/Documentation/about.md
index 8b35230..15c0e18 100644
--- a/src/main/resources/Documentation/about.md
+++ b/src/main/resources/Documentation/about.md
@@ -3,7 +3,8 @@
 ## Features
 - REST API to configure the options and labels.
 - Ability to prevent submission if there are unresolved comments.
-- Ability to require approval, and to consider approval from the change author or not.
+- Ability to require approval, and to consider approval from the uploader of the
+  latest patch set or not.
 - (soon!) a simple PolyGerrit UI to configure the labels and how they work.
 
 ### Inheritance
diff --git a/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/AbstractSimpleSubmitRulesIT.java b/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/AbstractSimpleSubmitRulesIT.java
deleted file mode 100644
index cf5e1fb..0000000
--- a/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/AbstractSimpleSubmitRulesIT.java
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (C) 2018 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.simplesubmitrules;
-
-import com.google.gerrit.acceptance.GitUtil;
-import com.google.gerrit.acceptance.LightweightPluginDaemonTest;
-import com.google.gerrit.acceptance.PushOneCommit;
-import com.google.gerrit.acceptance.TestPlugin;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.server.project.ProjectConfig;
-import java.util.function.Consumer;
-import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
-import org.eclipse.jgit.junit.TestRepository;
-import org.eclipse.jgit.lib.Config;
-import org.junit.Ignore;
-
-/** Base class used by IT tests, loads the Simple Submit Rules plugin. */
-@TestPlugin(
-    name = "my-plugin",
-    sysModule = "com.googlesource.gerrit.plugins.simplesubmitrules.Module")
-@Ignore
-public abstract class AbstractSimpleSubmitRulesIT extends LightweightPluginDaemonTest {
-  /** Helper method to change the project.config file using a provided consumer. */
-  protected void changeProjectConfig(Consumer<Config> callback) throws Exception {
-    TestRepository<InMemoryRepository> projectRepo = cloneProject(project, admin);
-    // Fetch permission ref
-    GitUtil.fetch(projectRepo, "refs/meta/config:cfg");
-    projectRepo.reset("cfg");
-
-    String rawConfig =
-        gApi.projects()
-            .name(project.get())
-            .branch(RefNames.REFS_CONFIG)
-            .file(ProjectConfig.PROJECT_CONFIG)
-            .asString();
-
-    Config config = new Config();
-    config.fromText(rawConfig);
-
-    // Apply our custom function to the config
-    callback.accept(config);
-
-    rawConfig = config.toText();
-
-    PushOneCommit push =
-        pushFactory.create(
-            db, admin.getIdent(), projectRepo, "Subject", ProjectConfig.PROJECT_CONFIG, rawConfig);
-    push.to(RefNames.REFS_CONFIG).assertOkStatus();
-  }
-}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/PluginIT.java b/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/PluginIT.java
new file mode 100644
index 0000000..d41ed1c
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/PluginIT.java
@@ -0,0 +1,158 @@
+// Copyright (C) 2018 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.simplesubmitrules;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.base.Charsets;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.gerrit.acceptance.LightweightPluginDaemonTest;
+import com.google.gerrit.acceptance.PushOneCommit;
+import com.google.gerrit.acceptance.RestResponse;
+import com.google.gerrit.acceptance.TestPlugin;
+import com.google.gerrit.common.RawInputUtil;
+import com.google.gerrit.common.data.LabelType;
+import com.google.gerrit.extensions.api.changes.ReviewInput;
+import com.google.gerrit.extensions.client.Side;
+import com.google.gerrit.extensions.common.ChangeInfo;
+import com.google.gerrit.extensions.common.SubmitRequirementInfo;
+import com.google.gerrit.extensions.restapi.RawInput;
+import com.google.gerrit.reviewdb.client.Project;
+import com.googlesource.gerrit.plugins.simplesubmitrules.api.CommentsRules;
+import com.googlesource.gerrit.plugins.simplesubmitrules.api.LabelDefinition;
+import com.googlesource.gerrit.plugins.simplesubmitrules.api.SubmitConfig;
+import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
+import org.eclipse.jgit.junit.TestRepository;
+import org.junit.Before;
+import org.junit.Test;
+
+@TestPlugin(
+    name = "my-plugin",
+    sysModule = "com.googlesource.gerrit.plugins.simplesubmitrules.Module")
+/** Overall end-to-end integration test for configuring labels and comments and merging changes. */
+public class PluginIT extends LightweightPluginDaemonTest {
+  private static final String JSON_TYPE = "application/json";
+
+  @Before
+  public void setUpCodeReviewLabel() throws Exception {
+    // TODO(hiesel): Remove once copy-down logic is in place
+    try (ProjectConfigUpdate u = updateProject(project)) {
+      LabelType codeReview = projectCache.getAllProjects().getLabelTypes().byLabel("Code-Review");
+      u.getConfig().getLabelSections().put("Code-Review", codeReview);
+      u.save();
+    }
+  }
+
+  @Test
+  public void singleApprovalIsSufficientByDefault() throws Exception {
+    PushOneCommit.Result r = createChange();
+    approve(r.getChangeId());
+    ChangeInfo changeInfo = gApi.changes().id(r.getChangeId()).get();
+    assertThat(changeInfo.submittable).isTrue();
+    assertThat(changeInfo.requirements).isEmpty();
+  }
+
+  @Test
+  public void unresolvedCommentsBlockSubmissionIfConfigured() throws Exception {
+    SubmitConfig config = new SubmitConfig(null, new CommentsRules(true));
+    postConfig(project, config);
+
+    // Create change as user
+    TestRepository<InMemoryRepository> userTestRepo = cloneProject(project, user);
+    PushOneCommit push = pushFactory.create(db, user.getIdent(), userTestRepo);
+    PushOneCommit.Result r = push.to("refs/for/master");
+
+    // Approve as admin
+    approve(r.getChangeId());
+
+    ReviewInput reviewInput = new ReviewInput();
+    ReviewInput.CommentInput c = new ReviewInput.CommentInput();
+    c.path = "a.txt";
+    c.side = Side.REVISION;
+    c.unresolved = true;
+    c.message = "nit: double  space.";
+    reviewInput.comments = ImmutableMap.of(c.path, ImmutableList.of(c));
+    revision(r).review(reviewInput);
+
+    ChangeInfo changeInfo = gApi.changes().id(r.getChangeId()).get();
+    assertThat(changeInfo.submittable).isFalse();
+    SubmitRequirementInfo noUnresolveComments =
+        new SubmitRequirementInfo(
+            "NOT_READY",
+            "Resolve all comments",
+            "unresolved_comments",
+            ImmutableMap.<String, String>of());
+    assertThat(changeInfo.requirements).containsExactly(noUnresolveComments);
+  }
+
+  @Test
+  public void uploaderApprovalDoesNotGrantSubmissionIfConfigured() throws Exception {
+    LabelDefinition codeReviewNoSelfApproval = new LabelDefinition("MaxWithBlock", true, null);
+    SubmitConfig config =
+        new SubmitConfig(ImmutableMap.of("Code-Review", codeReviewNoSelfApproval), null);
+    postConfig(project, config);
+
+    // Create change, put an unresolved comment on it and approve it.
+    PushOneCommit.Result r = createChange();
+    approve(r.getChangeId());
+
+    ChangeInfo changeInfo = gApi.changes().id(r.getChangeId()).get();
+    assertThat(changeInfo.submittable).isFalse();
+    SubmitRequirementInfo noSelfApproval =
+        new SubmitRequirementInfo(
+            "NOT_READY",
+            "Approval from non-uploader required",
+            "non_uploader_approval",
+            ImmutableMap.<String, String>of());
+    assertThat(changeInfo.requirements).containsExactly(noSelfApproval);
+  }
+
+  @Test
+  public void labelConfigsGetPersisted() throws Exception {
+    LabelDefinition codeReviewNoSelfApproval =
+        new LabelDefinition("MaxNoBlock", true, ImmutableSet.of("copyAllScoresIfNoChange"));
+    SubmitConfig config =
+        new SubmitConfig(ImmutableMap.of("Code-Review", codeReviewNoSelfApproval), null);
+    postConfig(project, config);
+
+    String currentConfig = adminRestSession.get(endpointUrl(project)).getEntityContent();
+    SubmitConfig parsedConfig = newGson().fromJson(currentConfig, SubmitConfig.class);
+    assertThat(parsedConfig.labels)
+        .isEqualTo(ImmutableMap.of("Code-Review", codeReviewNoSelfApproval));
+  }
+
+  @Test
+  public void commentsConfigGetPersisted() throws Exception {
+    SubmitConfig config = new SubmitConfig(null, new CommentsRules(true));
+    postConfig(project, config);
+
+    String currentConfig = adminRestSession.get(endpointUrl(project)).getEntityContent();
+    SubmitConfig parsedConfig = newGson().fromJson(currentConfig, SubmitConfig.class);
+    assertThat(parsedConfig.comments).isEqualTo(new CommentsRules(true));
+  }
+
+  private void postConfig(Project.NameKey project, SubmitConfig config) throws Exception {
+    RawInput rawInput =
+        RawInputUtil.create(newGson().toJson(config).getBytes(Charsets.UTF_8), JSON_TYPE);
+    RestResponse configResult = adminRestSession.putRaw(endpointUrl(project), rawInput);
+    configResult.assertOK();
+  }
+
+  private static String endpointUrl(Project.NameKey project) {
+    return "/projects/" + project.get() + "/simple-submit-rules";
+  }
+}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/config/ConfigServletIT.java b/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/config/ConfigServletIT.java
index e83b0e9..815198e 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/config/ConfigServletIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/config/ConfigServletIT.java
@@ -17,16 +17,20 @@
 import static com.google.gerrit.server.project.testing.Util.value;
 
 import com.google.common.base.Charsets;
+import com.google.gerrit.acceptance.LightweightPluginDaemonTest;
 import com.google.gerrit.acceptance.RestResponse;
+import com.google.gerrit.acceptance.TestPlugin;
 import com.google.gerrit.common.RawInputUtil;
 import com.google.gerrit.common.data.LabelFunction;
 import com.google.gerrit.extensions.restapi.RawInput;
 import com.google.gerrit.reviewdb.client.Project;
-import com.googlesource.gerrit.plugins.simplesubmitrules.AbstractSimpleSubmitRulesIT;
 import org.junit.Before;
 import org.junit.Test;
 
-public class ConfigServletIT extends AbstractSimpleSubmitRulesIT {
+@TestPlugin(
+    name = "my-plugin",
+    sysModule = "com.googlesource.gerrit.plugins.simplesubmitrules.Module")
+public class ConfigServletIT extends LightweightPluginDaemonTest {
   @Before
   public void setUp() throws Exception {
     configLabel(
@@ -70,7 +74,7 @@
                 + "    \"labels\": {\n"
                 + "        \"Code-Review\": {\n"
                 + "            \"function\": \"MaxWithBlock\",\n"
-                + "            \"ignore_self_approval\": false,\n"
+                + "            \"ignore_self_approval\": true,\n"
                 + "            \"copy_scores\": [\n"
                 + "                \"copyAllScoresIfNoChange\",\n"
                 + "                \"copyMinScore\",\n"
diff --git a/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/config/ConfigTranslatorTest.java b/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/config/ConfigTranslatorTest.java
index 332afb5..0528194 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/config/ConfigTranslatorTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/config/ConfigTranslatorTest.java
@@ -18,6 +18,7 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.gerrit.common.data.LabelType;
+import com.googlesource.gerrit.plugins.simplesubmitrules.api.LabelDefinition;
 import java.util.function.BiConsumer;
 import java.util.function.Predicate;
 import org.junit.Test;
@@ -66,7 +67,7 @@
       String copyScoreName, BiConsumer<LabelType, Boolean> functionToSet) {
 
     LabelType label = LabelType.withDefaultValues("Verified");
-    SubmitConfig.LabelDefinition labelDefinition = new SubmitConfig.LabelDefinition();
+    LabelDefinition labelDefinition = new LabelDefinition();
 
     functionToSet.accept(label, false);
     ConfigTranslator.extractLabelCopyScores(label, labelDefinition);
@@ -80,7 +81,7 @@
       String copyScoreName, BiConsumer<LabelType, Boolean> functionToSet) {
 
     LabelType label = LabelType.withDefaultValues("Verified");
-    SubmitConfig.LabelDefinition labelDefinition = new SubmitConfig.LabelDefinition();
+    LabelDefinition labelDefinition = new LabelDefinition();
 
     functionToSet.accept(label, true);
     ConfigTranslator.extractLabelCopyScores(label, labelDefinition);
diff --git a/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/rules/NoUnresolvedCommentsRuleIT.java b/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/rules/NoUnresolvedCommentsRuleIT.java
index 8e80861..ea58eb4 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/rules/NoUnresolvedCommentsRuleIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/rules/NoUnresolvedCommentsRuleIT.java
@@ -18,21 +18,25 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.gerrit.acceptance.LightweightPluginDaemonTest;
 import com.google.gerrit.acceptance.NoHttpd;
 import com.google.gerrit.acceptance.PushOneCommit;
+import com.google.gerrit.acceptance.TestPlugin;
 import com.google.gerrit.common.data.SubmitRecord;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
 import com.google.gerrit.extensions.client.Side;
 import com.google.gerrit.server.project.SubmitRuleOptions;
 import com.google.gerrit.server.query.change.ChangeData;
-import com.googlesource.gerrit.plugins.simplesubmitrules.AbstractSimpleSubmitRulesIT;
 import com.googlesource.gerrit.plugins.simplesubmitrules.SimpleSubmitRulesConfig;
 import java.util.Collection;
 import org.junit.Before;
 import org.junit.Test;
 
+@TestPlugin(
+    name = "my-plugin",
+    sysModule = "com.googlesource.gerrit.plugins.simplesubmitrules.Module")
 @NoHttpd
-public class NoUnresolvedCommentsRuleIT extends AbstractSimpleSubmitRulesIT {
+public class NoUnresolvedCommentsRuleIT extends LightweightPluginDaemonTest {
   private static final String FILENAME = "my.file";
 
   @Before
@@ -97,7 +101,8 @@
     assertThat(submitRecords).isEmpty();
   }
 
-  private PushOneCommit.Result createChangeWithComment(ReviewInput.CommentInput comment) throws Exception {
+  private PushOneCommit.Result createChangeWithComment(ReviewInput.CommentInput comment)
+      throws Exception {
     PushOneCommit.Result r = createChange("My change", FILENAME, "new content");
     ReviewInput reviewInput = new ReviewInput();
     reviewInput.comments = ImmutableMap.of(comment.path, ImmutableList.of(comment));
@@ -107,13 +112,12 @@
   }
 
   private void enableRule(boolean newState) throws Exception {
-    changeProjectConfig(
-        config ->
-            config.setBoolean(
-                "plugin",
-                plugin.getName(),
-                SimpleSubmitRulesConfig.KEY_BLOCK_IF_UNRESOLVED_COMMENTS,
-                newState));
+    try (ProjectConfigUpdate u = updateProject(project)) {
+      u.getConfig()
+          .getPluginConfig(plugin.getName())
+          .setBoolean(SimpleSubmitRulesConfig.KEY_BLOCK_IF_UNRESOLVED_COMMENTS, newState);
+      u.save();
+    }
   }
 
   private Collection<SubmitRecord> evaluate(ChangeData cd, SubmitRuleOptions options) {
diff --git a/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/rules/RequireNonAuthorApprovalRuleIT.java b/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/rules/RequireNonAuthorApprovalRuleIT.java
deleted file mode 100644
index 1f989d5..0000000
--- a/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/rules/RequireNonAuthorApprovalRuleIT.java
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (C) 2018 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.simplesubmitrules.rules;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.google.gerrit.acceptance.NoHttpd;
-import com.google.gerrit.acceptance.PushOneCommit;
-import com.google.gerrit.common.data.SubmitRecord;
-import com.google.gerrit.extensions.api.changes.ReviewInput;
-import com.google.gerrit.server.project.SubmitRuleOptions;
-import com.google.inject.Inject;
-import com.googlesource.gerrit.plugins.simplesubmitrules.AbstractSimpleSubmitRulesIT;
-import com.googlesource.gerrit.plugins.simplesubmitrules.SimpleSubmitRulesConfig;
-import java.util.Collection;
-import org.junit.Before;
-import org.junit.Test;
-
-@NoHttpd
-public class RequireNonAuthorApprovalRuleIT extends AbstractSimpleSubmitRulesIT {
-  private static final String FILENAME = "my.file";
-  @Inject private RequireNonAuthorApprovalRule rule;
-
-  @Before
-  public void enableRuleBeforeTest() throws Exception {
-    enableRule("Code-Review", true);
-  }
-
-  @Test
-  public void blocksWhenAutorIsOnlyApprover() throws Exception {
-    PushOneCommit.Result r = createChangeWithVote(2);
-
-    Collection<SubmitRecord> submitRecords =
-        rule.evaluate(r.getChange(), SubmitRuleOptions.defaults());
-
-    assertThat(submitRecords).hasSize(1);
-    SubmitRecord result = submitRecords.iterator().next();
-    assertThat(result.status).isEqualTo(SubmitRecord.Status.NOT_READY);
-    assertThat(result.labels).isNotEmpty();
-  }
-
-  @Test
-  public void doesNothingByDefault() throws Exception {
-    PushOneCommit.Result r = createChangeWithVote(+2);
-
-    enableRule("Code-Review", false);
-
-    Collection<SubmitRecord> submitRecords =
-        rule.evaluate(r.getChange(), SubmitRuleOptions.defaults());
-    assertThat(submitRecords).isEmpty();
-  }
-
-  private PushOneCommit.Result createChangeWithVote(int value) throws Exception {
-    PushOneCommit.Result r = createChange("My change", FILENAME, "new content");
-    ReviewInput reviewInput = new ReviewInput();
-    reviewInput.label("Code-Review", value);
-    revision(r).review(reviewInput);
-
-    return r;
-  }
-
-  private void enableRule(String labelName, boolean newState) throws Exception {
-    changeProjectConfig(
-        config ->
-            config.setBoolean(
-                labelName,
-                null,
-                SimpleSubmitRulesConfig.KEY_REQUIRE_NON_AUTHOR_APPROVAL,
-                newState));
-  }
-}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/rules/RequireNonAuthorApprovalRuleTest.java b/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/rules/RequireNonAuthorApprovalRuleTest.java
deleted file mode 100644
index 7324f55..0000000
--- a/src/test/java/com/googlesource/gerrit/plugins/simplesubmitrules/rules/RequireNonAuthorApprovalRuleTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (C) 2018 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.simplesubmitrules.rules;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.googlesource.gerrit.plugins.simplesubmitrules.rules.RequireNonAuthorApprovalRule.getApprovalsForLabel;
-
-import com.google.common.collect.ImmutableList;
-import com.google.gerrit.common.data.LabelType;
-import com.google.gerrit.common.data.LabelValue;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.LabelId;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.PatchSetApproval;
-import java.time.Instant;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-import org.junit.Test;
-
-public class RequireNonAuthorApprovalRuleTest {
-  private static final Change.Id CHANGE_ID = new Change.Id(100);
-  private static final PatchSet.Id PS_ID = new PatchSet.Id(CHANGE_ID, 1);
-  private static final LabelType VERIFIED = makeLabel("Verified");
-  private static final Account.Id USER1 = makeAccount(100001);
-  private static final Account.Id USER2 = makeAccount(100002);
-
-  @Test
-  public void filtersByLabel() {
-    LabelType codeReview = makeLabel("Code-Review");
-    PatchSetApproval approvalVerified = makeApproval(VERIFIED.getLabelId(), USER1, 2);
-    PatchSetApproval approvalCr = makeApproval(codeReview.getLabelId(), USER1, 2);
-
-    Collection<PatchSetApproval> filteredApprovals =
-        getApprovalsForLabel(ImmutableList.of(approvalVerified, approvalCr), codeReview, USER2);
-
-    assertThat(filteredApprovals).containsExactly(approvalCr);
-  }
-
-  @Test
-  public void filtersVotesFromUser() {
-    PatchSetApproval approvalM2 = makeApproval(VERIFIED.getLabelId(), USER1, -2);
-    PatchSetApproval approvalM1 = makeApproval(VERIFIED.getLabelId(), USER1, -1);
-
-    ImmutableList<PatchSetApproval> approvals =
-        ImmutableList.of(
-            approvalM2,
-            approvalM1,
-            makeApproval(VERIFIED.getLabelId(), USER1, 0),
-            makeApproval(VERIFIED.getLabelId(), USER1, +1),
-            makeApproval(VERIFIED.getLabelId(), USER1, +2));
-
-    Collection<PatchSetApproval> filteredApprovals =
-        getApprovalsForLabel(approvals, VERIFIED, USER1);
-
-    assertThat(filteredApprovals).containsExactly(approvalM1, approvalM2);
-  }
-
-  private static LabelType makeLabel(String labelName) {
-    List<LabelValue> values = new ArrayList<>();
-    // The label text is irrelevant here, only the numerical value is used
-    values.add(new LabelValue((short) -2, "-2"));
-    values.add(new LabelValue((short) -1, "-1"));
-    values.add(new LabelValue((short) 0, "No vote."));
-    values.add(new LabelValue((short) 1, "+1"));
-    values.add(new LabelValue((short) 2, "+2"));
-    return new LabelType(labelName, values);
-  }
-
-  private static PatchSetApproval makeApproval(LabelId labelId, Account.Id accountId, int value) {
-    PatchSetApproval.Key key = makeKey(PS_ID, accountId, labelId);
-    return new PatchSetApproval(key, (short) value, Date.from(Instant.now()));
-  }
-
-  private static PatchSetApproval.Key makeKey(
-      PatchSet.Id psId, Account.Id accountId, LabelId labelId) {
-    return new PatchSetApproval.Key(psId, accountId, labelId);
-  }
-
-  private static Account.Id makeAccount(int account) {
-    return new Account.Id(account);
-  }
-}