Merge "CreateLabel/SetLabel: Reject duplicate values"
diff --git a/java/com/google/gerrit/server/restapi/project/LabelDefinitionInputParser.java b/java/com/google/gerrit/server/restapi/project/LabelDefinitionInputParser.java
index a45c67f..1e288f4 100644
--- a/java/com/google/gerrit/server/restapi/project/LabelDefinitionInputParser.java
+++ b/java/com/google/gerrit/server/restapi/project/LabelDefinitionInputParser.java
@@ -24,10 +24,12 @@
 import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.server.project.RefPattern;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Optional;
+import java.util.Set;
 
 public class LabelDefinitionInputParser {
   public static LabelFunction parseFunction(String functionString) throws BadRequestException {
@@ -39,6 +41,7 @@
   public static List<LabelValue> parseValues(Map<String, String> values)
       throws BadRequestException {
     List<LabelValue> valueList = new ArrayList<>();
+    Set<Short> allValues = new HashSet<>();
     for (Entry<String, String> e : values.entrySet()) {
       short value;
       try {
@@ -46,6 +49,9 @@
       } catch (NumberFormatException ex) {
         throw new BadRequestException("invalid value: " + e.getKey(), ex);
       }
+      if (!allValues.add(value)) {
+        throw new BadRequestException("duplicate value: " + value);
+      }
       String valueDescription = e.getValue().trim();
       if (valueDescription.isEmpty()) {
         throw new BadRequestException("description for value '" + e.getKey() + "' cannot be empty");
diff --git a/javatests/com/google/gerrit/acceptance/rest/project/CreateLabelIT.java b/javatests/com/google/gerrit/acceptance/rest/project/CreateLabelIT.java
index 28e8b14..57a1e56 100644
--- a/javatests/com/google/gerrit/acceptance/rest/project/CreateLabelIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/project/CreateLabelIT.java
@@ -169,6 +169,21 @@
   }
 
   @Test
+  public void cannotCreateLabelWithDuplicateValues() throws Exception {
+    LabelDefinitionInput input = new LabelDefinitionInput();
+    // Positive values can be specified as '<value>' or '+<value>'.
+    input.values =
+        ImmutableMap.of(
+            "+1", "Looks Good", "1", "Looks Good", "0", "Don't Know", "-1", "Looks Bad");
+
+    BadRequestException thrown =
+        assertThrows(
+            BadRequestException.class,
+            () -> gApi.projects().name(allProjects.get()).label("Foo").create(input));
+    assertThat(thrown).hasMessageThat().contains("duplicate value: 1");
+  }
+
+  @Test
   public void cannotCreateLabelWithInvalidDefaultValue() throws Exception {
     LabelDefinitionInput input = new LabelDefinitionInput();
     input.values = ImmutableMap.of("+1", "Looks Good", "0", "Don't Know", "-1", "Looks Bad");
diff --git a/javatests/com/google/gerrit/acceptance/rest/project/SetLabelIT.java b/javatests/com/google/gerrit/acceptance/rest/project/SetLabelIT.java
index 9cba930..97b795f 100644
--- a/javatests/com/google/gerrit/acceptance/rest/project/SetLabelIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/project/SetLabelIT.java
@@ -323,6 +323,21 @@
   }
 
   @Test
+  public void cannotSetDuplicateValues() throws Exception {
+    LabelDefinitionInput input = new LabelDefinitionInput();
+    // Positive values can be specified as '<value>' or '+<value>'.
+    input.values =
+        ImmutableMap.of(
+            "+1", "Looks Good", "1", "Looks Good", "0", "Don't Know", "-1", "Looks Bad");
+
+    BadRequestException thrown =
+        assertThrows(
+            BadRequestException.class,
+            () -> gApi.projects().name(allProjects.get()).label("Code-Review").update(input));
+    assertThat(thrown).hasMessageThat().contains("duplicate value: 1");
+  }
+
+  @Test
   public void updateDefaultValue() throws Exception {
     LabelDefinitionInput input = new LabelDefinitionInput();
     input.defaultValue = 1;