// Copyright 2014 The Bazel Authors. All rights reserved.
//
// 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.devtools.common.options;

import static com.google.common.truth.Truth.assertThat;
import static com.google.devtools.build.lib.testutil.MoreAsserts.assertThrows;
import static com.google.devtools.common.options.OptionsParser.newOptionsParser;
import static java.util.Arrays.asList;
import static org.junit.Assert.fail;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.common.options.Converters.CommaSeparatedOptionListConverter;
import com.google.devtools.common.options.OptionPriority.PriorityCategory;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Predicate;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests {@link OptionsParser}. */
@RunWith(JUnit4.class)
public class OptionsParserTest {

  /** Dummy comment (linter suppression) */
  public static class BadOptions extends OptionsBase {
    @Option(
      name = "foo",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "false"
    )
    public boolean foo1;

    @Option(
      name = "foo",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "false"
    )
    public boolean foo2;
  }

  @Test
  public void errorsDuringConstructionAreWrapped() {
    OptionsParser.ConstructionException e =
        assertThrows(
            OptionsParser.ConstructionException.class, () -> newOptionsParser(BadOptions.class));
    assertThat(e).hasCauseThat().isInstanceOf(DuplicateOptionDeclarationException.class);
  }

  public static class ExampleFoo extends OptionsBase {

    @Option(
      name = "foo",
      category = "one",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "defaultFoo"
    )
    public String foo;

    @Option(
      name = "bar",
      category = "two",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "42"
    )
    public int bar;

    @Option(
      name = "bing",
      category = "one",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "",
      allowMultiple = true
    )
    public List<String> bing;

    @Option(
      name = "bang",
      category = "one",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "",
      converter = StringConverter.class,
      allowMultiple = true
    )
    public List<String> bang;

    @Option(
      name = "nodoc",
      documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "",
      allowMultiple = false
    )
    public String nodoc;
  }

  public static class ExampleBaz extends OptionsBase {

    @Option(
      name = "baz",
      category = "one",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "defaultBaz"
    )
    public String baz;
  }

  /** Subclass of an options class. */
  public static class ExampleBazSubclass extends ExampleBaz {

    @Option(
      name = "baz_subclass",
      category = "one",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "defaultBazSubclass"
    )
    public String bazSubclass;
  }

  /**
   * Example with empty to null string converter
   */
  public static class ExampleBoom extends OptionsBase {
    @Option(
      name = "boom",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "defaultBoom",
      converter = EmptyToNullStringConverter.class
    )
    public String boom;
  }

  /**
   * Example with internal options
   */
  public static class ExampleInternalOptions extends OptionsBase {
    @Option(
      name = "internal_boolean",
      metadataTags = {OptionMetadataTag.INTERNAL},
      documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "true"
    )
    public boolean privateBoolean;

    @Option(
      name = "internal_string",
      metadataTags = {OptionMetadataTag.INTERNAL},
      documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "super secret"
    )
    public String privateString;
  }

  public static class StringConverter implements Converter<String> {
    @Override
    public String convert(String input) {
      return input;
    }
    @Override
    public String getTypeDescription() {
      return "a string";
    }
  }

  /**
   * A converter that defaults to null if the input is the empty string
   */
  public static class EmptyToNullStringConverter extends StringConverter {
    @Override
    public String convert(String input) {
      return input.isEmpty() ? null : input;
    }
  }

  @Test
  public void parseWithMultipleOptionsInterfaces()
      throws OptionsParsingException {
    OptionsParser parser = newOptionsParser(ExampleFoo.class, ExampleBaz.class);
    parser.parse("--baz=oops", "--bar", "17");
    ExampleFoo foo = parser.getOptions(ExampleFoo.class);
    assertThat(foo.foo).isEqualTo("defaultFoo");
    assertThat(foo.bar).isEqualTo(17);
    ExampleBaz baz = parser.getOptions(ExampleBaz.class);
    assertThat(baz.baz).isEqualTo("oops");
  }

  @Test
  public void parseWithOptionsInheritance() throws OptionsParsingException {
    OptionsParser parser = newOptionsParser(ExampleBazSubclass.class);
    parser.parse("--baz_subclass=cat", "--baz=dog");
    ExampleBazSubclass subclassOptions = parser.getOptions(ExampleBazSubclass.class);
    assertThat(subclassOptions.bazSubclass).isEqualTo("cat");
    assertThat(subclassOptions.baz).isEqualTo("dog");
    ExampleBaz options = parser.getOptions(ExampleBaz.class);
    // This is a test showcasing the lack of functionality for retrieving parsed options at a
    // superclass type class type. If there's a need for this functionality, we can add it later.
    assertThat(options).isNull();
  }

  @Test
  public void parserWithUnknownOption() {
    OptionsParser parser = newOptionsParser(ExampleFoo.class, ExampleBaz.class);
    OptionsParsingException e =
        assertThrows(OptionsParsingException.class, () -> parser.parse("--unknown", "option"));
    assertThat(e.getInvalidArgument()).isEqualTo("--unknown");
    assertThat(e).hasMessageThat().isEqualTo("Unrecognized option: --unknown");
    assertThat(parser.getResidue()).isEmpty();
  }

  @Test
  public void parserWithSingleDashOption_notAllowed() throws OptionsParsingException {
    OptionsParser parser = newOptionsParser(ExampleFoo.class, ExampleBaz.class);
    parser.setAllowSingleDashLongOptions(false);
    assertThrows(OptionsParsingException.class, () -> parser.parse("-baz=oops", "-bar", "17"));
  }

  @Test
  public void parserWithSingleDashOption() throws OptionsParsingException {
    OptionsParser parser = newOptionsParser(ExampleFoo.class, ExampleBaz.class);
    parser.setAllowSingleDashLongOptions(true);
    parser.parse("-baz=oops", "-bar", "17");
    ExampleFoo foo = parser.getOptions(ExampleFoo.class);
    assertThat(foo.foo).isEqualTo("defaultFoo");
    assertThat(foo.bar).isEqualTo(17);
    ExampleBaz baz = parser.getOptions(ExampleBaz.class);
    assertThat(baz.baz).isEqualTo("oops");
  }

  @Test
  public void parsingFailsWithUnknownOptions() {
    OptionsParser parser = newOptionsParser(ExampleFoo.class, ExampleBaz.class);
    List<String> unknownOpts = asList("--unknown", "option", "--more_unknowns");
    OptionsParsingException e =
        assertThrows(OptionsParsingException.class, () -> parser.parse(unknownOpts));
    assertThat(e.getInvalidArgument()).isEqualTo("--unknown");
      assertThat(e).hasMessageThat().isEqualTo("Unrecognized option: --unknown");
      assertThat(parser.getOptions(ExampleFoo.class)).isNotNull();
    assertThat(parser.getOptions(ExampleBaz.class)).isNotNull();
  }

  @Test
  public void parsingFailsWithInternalBooleanOptionAsIfUnknown() {
    OptionsParser parser = newOptionsParser(ExampleInternalOptions.class);
    List<String> internalOpts = asList("--internal_boolean");
    OptionsParsingException e =
        assertThrows(OptionsParsingException.class, () -> parser.parse(internalOpts));
    assertThat(e.getInvalidArgument()).isEqualTo("--internal_boolean");
      assertThat(e).hasMessageThat().isEqualTo("Unrecognized option: --internal_boolean");
    assertThat(parser.getOptions(ExampleInternalOptions.class)).isNotNull();
  }

  @Test
  public void parsingFailsWithNegatedInternalBooleanOptionAsIfUnknown() {
    OptionsParser parser = newOptionsParser(ExampleInternalOptions.class);
    List<String> internalOpts = asList("--nointernal_boolean");
    OptionsParsingException e =
        assertThrows(OptionsParsingException.class, () -> parser.parse(internalOpts));
    assertThat(e.getInvalidArgument()).isEqualTo("--nointernal_boolean");
      assertThat(e).hasMessageThat().isEqualTo("Unrecognized option: --nointernal_boolean");
    assertThat(parser.getOptions(ExampleInternalOptions.class)).isNotNull();
  }

  @Test
  public void parsingFailsForInternalOptionWithValueInSameArgAsIfUnknown() {
    OptionsParser parser = newOptionsParser(ExampleInternalOptions.class);
    List<String> internalOpts = asList("--internal_string=any_value");
    OptionsParsingException e =
        assertThrows(
            "parsing should have failed for including a private option",
            OptionsParsingException.class,
            () -> parser.parse(internalOpts));
    assertThat(e.getInvalidArgument()).isEqualTo("--internal_string=any_value");
      assertThat(e).hasMessageThat().isEqualTo("Unrecognized option: --internal_string=any_value");
    assertThat(parser.getOptions(ExampleInternalOptions.class)).isNotNull();
  }

  @Test
  public void parsingFailsForInternalOptionWithValueInSeparateArgAsIfUnknown() {
    OptionsParser parser = newOptionsParser(ExampleInternalOptions.class);
    List<String> internalOpts = asList("--internal_string", "any_value");
    OptionsParsingException e =
        assertThrows(
            "parsing should have failed for including a private option",
            OptionsParsingException.class,
            () -> parser.parse(internalOpts));
    assertThat(e.getInvalidArgument()).isEqualTo("--internal_string");
      assertThat(e).hasMessageThat().isEqualTo("Unrecognized option: --internal_string");
    assertThat(parser.getOptions(ExampleInternalOptions.class)).isNotNull();
  }

  @Test
  public void parseKnownAndUnknownOptions() {
    OptionsParser parser = newOptionsParser(ExampleFoo.class, ExampleBaz.class);
    List<String> opts = asList("--bar", "17", "--unknown", "option");
    OptionsParsingException e =
        assertThrows(OptionsParsingException.class, () -> parser.parse(opts));
    assertThat(e.getInvalidArgument()).isEqualTo("--unknown");
      assertThat(e).hasMessageThat().isEqualTo("Unrecognized option: --unknown");
      assertThat(parser.getOptions(ExampleFoo.class)).isNotNull();
    assertThat(parser.getOptions(ExampleBaz.class)).isNotNull();
  }

  @Test
  public void parseAndOverrideWithEmptyStringToObtainNullValueInOption()
      throws OptionsParsingException {
    OptionsParser parser = newOptionsParser(ExampleBoom.class);
    // Override --boom value to the empty string
    parser.parse("--boom=");
    ExampleBoom boom = parser.getOptions(ExampleBoom.class);
    // The converted value is intentionally null since boom uses the EmptyToNullStringConverter
    assertThat(boom.boom).isNull();
  }

  public static class CategoryTest extends OptionsBase {
    @Option(
      name = "swiss_bank_account_number",
      documentationCategory =
          OptionDocumentationCategory.UNDOCUMENTED, // Not printed in usage messages!
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "123456789"
    )
    public int swissBankAccountNumber;

    @Option(
      name = "student_bank_account_number",
      category = "one",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "987654321"
    )
    public int studentBankAccountNumber;
  }

  @Test
  public void getOptionsAndGetResidueWithNoCallToParse() {
    // With no call to parse(), all options are at default values, and there's
    // no reside.
    assertThat(newOptionsParser(ExampleFoo.class).getOptions(ExampleFoo.class).foo)
        .isEqualTo("defaultFoo");
    assertThat(newOptionsParser(ExampleFoo.class).getResidue()).isEmpty();
  }

  @Test
  public void parserCanBeCalledRepeatedly() throws OptionsParsingException {
    OptionsParser parser = newOptionsParser(ExampleFoo.class);
    parser.parse("--foo", "foo1");
    assertThat(parser.getOptions(ExampleFoo.class).foo).isEqualTo("foo1");
    parser.parse();
    assertThat(parser.getOptions(ExampleFoo.class).foo).isEqualTo("foo1"); // no change
    parser.parse("--foo", "foo2");
    assertThat(parser.getOptions(ExampleFoo.class).foo).isEqualTo("foo2"); // updated
  }

  @Test
  public void multipleOccuringOption() throws OptionsParsingException {
    OptionsParser parser = newOptionsParser(ExampleFoo.class);
    parser.parse("--bing", "abcdef", "--foo", "foo1", "--bing", "123456" );
    assertThat(parser.getOptions(ExampleFoo.class).bing).containsExactly("abcdef", "123456");
  }

  @Test
  public void multipleOccurringOptionWithConverter() throws OptionsParsingException {
    // --bang is the same as --bing except that it has a "converter" specified.
    // This test also tests option values with embedded commas and spaces.
    OptionsParser parser = newOptionsParser(ExampleFoo.class);
    parser.parse("--bang", "abc,def ghi", "--foo", "foo1", "--bang", "123456" );
    assertThat(parser.getOptions(ExampleFoo.class).bang).containsExactly("abc,def ghi", "123456");
  }

  @Test
  public void parserIgnoresOptionsAfterMinusMinus()
      throws OptionsParsingException {
    OptionsParser parser = newOptionsParser(ExampleFoo.class, ExampleBaz.class);
    parser.parse("--foo", "well", "--baz", "here", "--", "--bar", "ignore");
    ExampleFoo foo = parser.getOptions(ExampleFoo.class);
    ExampleBaz baz = parser.getOptions(ExampleBaz.class);
    assertThat(foo.foo).isEqualTo("well");
    assertThat(baz.baz).isEqualTo("here");
    assertThat(foo.bar).isEqualTo(42); // the default!
    assertThat(parser.getResidue()).containsExactly("--bar", "ignore").inOrder();
  }

  @Test
  public void parserThrowsExceptionIfResidueIsNotAllowed() {
    OptionsParser parser = newOptionsParser(ExampleFoo.class);
    parser.setAllowResidue(false);
    OptionsParsingException e =
        assertThrows(
            OptionsParsingException.class, () -> parser.parse("residue", "is", "not", "OK"));
    assertThat(e).hasMessageThat().isEqualTo("Unrecognized arguments: residue is not OK");
  }

  @Test
  public void multipleCallsToParse() throws Exception {
    OptionsParser parser = newOptionsParser(ExampleFoo.class);
    parser.setAllowResidue(true);
    parser.parse("--foo", "one", "--bar", "43", "unknown1");
    parser.parse("--foo", "two", "unknown2");
    ExampleFoo foo = parser.getOptions(ExampleFoo.class);
    assertThat(foo.foo).isEqualTo("two"); // second call takes precedence
    assertThat(foo.bar).isEqualTo(43);
    assertThat(parser.getResidue()).containsExactly("unknown1", "unknown2").inOrder();
  }

  // Regression test for a subtle bug!  The toString of each options interface
  // instance was printing out key=value pairs for all flags in the
  // OptionsParser, not just those belonging to the specific interface type.
  @Test
  public void toStringDoesntIncludeFlagsForOtherOptionsInParserInstance()
      throws Exception {
    OptionsParser parser = newOptionsParser(ExampleFoo.class, ExampleBaz.class);
    parser.parse("--foo", "foo", "--bar", "43", "--baz", "baz");

    String fooString = parser.getOptions(ExampleFoo.class).toString();
    if (!fooString.contains("foo=foo") ||
        !fooString.contains("bar=43") ||
        !fooString.contains("ExampleFoo") ||
        fooString.contains("baz=baz")) {
      fail("ExampleFoo.toString() is incorrect: " + fooString);
    }

    String bazString = parser.getOptions(ExampleBaz.class).toString();
    if (!bazString.contains("baz=baz") ||
        !bazString.contains("ExampleBaz") ||
        bazString.contains("foo=foo") ||
        bazString.contains("bar=43")) {
      fail("ExampleBaz.toString() is incorrect: " + bazString);
    }
  }

  // Regression test for another subtle bug!  The toString was printing all the
  // explicitly-specified options, even if they were at their default values,
  // causing toString equivalence to diverge from equals().
  @Test
  public void toStringIsIndependentOfExplicitCommandLineOptions() throws Exception {
    ExampleFoo foo1 = Options.parse(ExampleFoo.class).getOptions();
    ExampleFoo foo2 = Options.parse(ExampleFoo.class, "--bar", "42").getOptions();
    assertThat(foo2).isEqualTo(foo1);
    assertThat(foo2.toString()).isEqualTo(foo1.toString());

    Map<String, Object> expectedMap = new ImmutableMap.Builder<String, Object>().
        put("bing", Collections.emptyList()).
        put("bar", 42).
        put("nodoc", "").
        put("bang", Collections.emptyList()).
        put("foo", "defaultFoo").build();

    assertThat(foo1.asMap()).isEqualTo(expectedMap);
    assertThat(foo2.asMap()).isEqualTo(expectedMap);
  }

  // Regression test for yet another subtle bug!  The inherited options weren't
  // being printed by toString.  One day, a real rain will come and wash all
  // this scummy code off the streets.
  public static class DerivedBaz extends ExampleBaz {
    @Option(
      name = "derived",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "defaultDerived"
    )
    public String derived;
  }

  @Test
  public void toStringPrintsInheritedOptionsToo_Duh() throws Exception {
    DerivedBaz derivedBaz = Options.parse(DerivedBaz.class).getOptions();
    String derivedBazString = derivedBaz.toString();
    if (!derivedBazString.contains("derived=defaultDerived") ||
        !derivedBazString.contains("baz=defaultBaz")) {
      fail("DerivedBaz.toString() is incorrect: " + derivedBazString);
    }
  }

  // Tests for new default value override mechanism
  public static class CustomOptions extends OptionsBase {
    @Option(
      name = "simple",
      category = "custom",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "simple default"
    )
    public String simple;

    @Option(
      name = "multipart_name",
      category = "custom",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "multipart default"
    )
    public String multipartName;
  }

  @Test
  public void assertDefaultStringsForCustomOptions() throws OptionsParsingException {
    CustomOptions options = Options.parse(CustomOptions.class).getOptions();
    assertThat(options.simple).isEqualTo("simple default");
    assertThat(options.multipartName).isEqualTo("multipart default");
  }

  public static class NullTestOptions extends OptionsBase {
    @Option(
      name = "simple",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null"
    )
    public String simple;
  }

  @Test
  public void defaultNullStringGivesNull() throws Exception {
    NullTestOptions options = Options.parse(NullTestOptions.class).getOptions();
    assertThat(options.simple).isNull();
  }

  public static class ImplicitDependencyOptions extends OptionsBase {
    @Option(
      name = "first",
      implicitRequirements = "--second=second",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null"
    )
    public String first;

    @Option(
      name = "second",
      implicitRequirements = "--third=third",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null"
    )
    public String second;

    @Option(
      name = "third",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null"
    )
    public String third;
  }

  @Test
  public void implicitDependencyHasImplicitDependency() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(ImplicitDependencyOptions.class);
    parser.parse(
        OptionPriority.PriorityCategory.COMMAND_LINE, null, Arrays.asList("--first=first"));
    assertThat(parser.getOptions(ImplicitDependencyOptions.class).first).isEqualTo("first");
    assertThat(parser.getOptions(ImplicitDependencyOptions.class).second).isEqualTo("second");
    assertThat(parser.getOptions(ImplicitDependencyOptions.class).third).isEqualTo("third");
    assertThat(parser.getWarnings()).isEmpty();
  }

  public static class BadImplicitDependencyOptions extends OptionsBase {
    @Option(
      name = "first",
      implicitRequirements = "xxx",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null"
    )
    public String first;
  }

  @Test
  public void badImplicitDependency() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(BadImplicitDependencyOptions.class);
    try {
      parser.parse(
          OptionPriority.PriorityCategory.COMMAND_LINE, null, Arrays.asList("--first=first"));
    } catch (AssertionError e) {
      /* Expected error. */
      return;
    }
    fail();
  }

  public static class BadExpansionOptions extends OptionsBase {
    @Option(
      name = "first",
      expansion = {"xxx"},
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null"
    )
    public Void first;
  }

  @Test
  public void badExpansionOptions() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(BadExpansionOptions.class);
    try {
      parser.parse(OptionPriority.PriorityCategory.COMMAND_LINE, null, Arrays.asList("--first"));
    } catch (AssertionError e) {
      /* Expected error. */
      return;
    }
    fail();
  }

  /** NullExpansionOptions */
  public static class NullExpansionsOptions extends OptionsBase {

    /** ExpFunc */
    public static class ExpFunc implements ExpansionFunction {
      @Override
      public ImmutableList<String> getExpansion(IsolatedOptionsData optionsData) {
        return null;
      }
    }

    @Option(
      name = "badness",
      expansionFunction = ExpFunc.class,
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null"
    )
    public Void badness;
  }

  @Test
  public void nullExpansions() throws Exception {
    // Ensure that we get the NPE at the time of parser construction, not later when actually
    // parsing.
    OptionsParser.ConstructionException e =
        assertThrows(
            "Should have failed due to null expansion function result",
            OptionsParser.ConstructionException.class,
            () -> newOptionsParser(NullExpansionsOptions.class));
    assertThat(e).hasCauseThat().isInstanceOf(NullPointerException.class);
    assertThat(e).hasCauseThat().hasMessageThat().contains("null value in entry");
  }

  /** ExpansionOptions */
  public static class ExpansionOptions extends OptionsBase {
    @Option(
      name = "underlying",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null"
    )
    public String underlying;

    @Option(
      name = "expands",
      expansion = {"--underlying=from_expansion"},
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null"
    )
    public Void expands;

    /** ExpFunc */
    public static class ExpFunc implements ExpansionFunction {
      @Override
      public ImmutableList<String> getExpansion(IsolatedOptionsData optionsData) {
        return ImmutableList.of("--expands");
      }
    }

    @Option(
      name = "expands_by_function",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null",
      expansionFunction = ExpFunc.class
    )
    public Void expandsByFunction;
  }

  /** ExpansionMultipleOptions */
  public static class ExpansionMultipleOptions extends OptionsBase {
    @Option(
      name = "underlying",
      defaultValue = "null",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      allowMultiple = true
    )
    public List<String> underlying;

    /** ExpFunc */
    public static class ExpFunc implements ExpansionFunction {
      @Override
      public ImmutableList<String> getExpansion(IsolatedOptionsData optionsData) {
        return ImmutableList.of("--underlying=pre_value", "--underlying=post_value");
      }
    }

    @Option(
      name = "expands_by_function",
      defaultValue = "null",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      expansionFunction = ExpFunc.class
    )
    public Void expandsByFunction;
  }

  @Test
  public void describeOptionsWithExpansion() throws Exception {
    // We have to test this here rather than in OptionsTest because expansion functions require
    // that an options parser be constructed.
    OptionsParser parser = OptionsParser.newOptionsParser(ExpansionOptions.class);
    String usage =
        parser.describeOptionsWithDeprecatedCategories(
            ImmutableMap.<String, String>of(), OptionsParser.HelpVerbosity.LONG);
    assertThat(usage).contains("  --expands\n      Expands to: --underlying=from_expansion");
    assertThat(usage).contains("  --expands_by_function\n      Expands to: --expands");
  }

  @Test
  public void overrideExpansionWithExplicit() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(ExpansionOptions.class);
    parser.parse(
        OptionPriority.PriorityCategory.COMMAND_LINE,
        null,
        Arrays.asList("--expands", "--underlying=direct_value"));
    ExpansionOptions options = parser.getOptions(ExpansionOptions.class);
    assertThat(options.underlying).isEqualTo("direct_value");
    assertThat(parser.getWarnings()).isEmpty();
  }

  @Test
  public void testExpansionOriginIsPropagatedToOption() throws OptionsParsingException {
    OptionsParser parser = OptionsParser.newOptionsParser(ExpansionOptions.class);
    parser.parse(OptionPriority.PriorityCategory.COMMAND_LINE, null, Arrays.asList("--expands"));
    OptionValueDescription expansionDescription = parser.getOptionValueDescription("expands");
    assertThat(expansionDescription).isNotNull();

    // In order to have access to the ParsedOptionDescription tracked by the value of 'underlying'
    // we have to know that this option is a "single valued" option.
    OptionValueDescription optionValue = parser.getOptionValueDescription("underlying");
    assertThat(optionValue).isNotNull();
    assertThat(optionValue.getSourceString()).matches("expanded from option '--expands'");
    assertThat(optionValue.getCanonicalInstances()).isNotNull();
    assertThat(optionValue.getCanonicalInstances()).hasSize(1);

    ParsedOptionDescription effectiveInstance = optionValue.getCanonicalInstances().get(0);
    assertThat(effectiveInstance.getExpandedFrom().getOptionDefinition())
        .isSameInstanceAs(expansionDescription.getOptionDefinition());
    assertThat(effectiveInstance.getImplicitDependent()).isNull();

    assertThat(parser.getWarnings()).isEmpty();
  }

  @Test
  public void overrideExplicitWithExpansion() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(ExpansionOptions.class);
    parser.parse(
        OptionPriority.PriorityCategory.COMMAND_LINE,
        null,
        Arrays.asList("--underlying=direct_value", "--expands"));
    ExpansionOptions options = parser.getOptions(ExpansionOptions.class);
    assertThat(options.underlying).isEqualTo("from_expansion");
    assertThat(parser.getWarnings())
        .containsExactly(
            "option '--expands' was expanded and now overrides the explicit option "
                + "--underlying=direct_value with --underlying=from_expansion");
  }

  @Test
  public void noWarningsWhenOverrideExplicitWithExpansion() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(ExpansionOptions.class);
    parser.parse(
        OptionPriority.PriorityCategory.RC_FILE,
        null,
        Arrays.asList("--underlying=direct_value", "--expands"));
    ExpansionOptions options = parser.getOptions(ExpansionOptions.class);
    assertThat(options.underlying).isEqualTo("from_expansion");
    assertThat(parser.getWarnings())
        .doesNotContain(
            "option '--expands' was expanded and now overrides the explicit option "
                + "--underlying=direct_value with --underlying=from_expansion");
  }

  @Test
  public void noWarningsWhenValueNotChanged() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(ExpansionOptions.class);
    parser.parse(
        OptionPriority.PriorityCategory.COMMAND_LINE,
        null,
        Arrays.asList("--underlying=from_expansion", "--expands"));
    ExpansionOptions options = parser.getOptions(ExpansionOptions.class);
    assertThat(options.underlying).isEqualTo("from_expansion");
    // The expansion option overrides the explicit option, but it is the same value, so expect
    // no warning.
    assertThat(parser.getWarnings()).isEmpty();
  }

  // Makes sure the expansion options are expanded in the right order if they affect flags that
  // allow multiples.
  @Test
  public void multipleExpansionOptionsWithValue() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(ExpansionMultipleOptions.class);
    parser.parse(
        OptionPriority.PriorityCategory.COMMAND_LINE,
        null,
        Arrays.asList(
            "--expands_by_function", "--underlying=direct_value", "--expands_by_function"));
    ExpansionMultipleOptions options = parser.getOptions(ExpansionMultipleOptions.class);
    assertThat(options.underlying)
        .containsExactly("pre_value", "post_value", "direct_value", "pre_value", "post_value")
        .inOrder();
    assertThat(parser.getWarnings()).isEmpty();
  }

  @Test
  public void checkExpansionValueWarning() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(ExpansionMultipleOptions.class);
    parser.parse(
        OptionPriority.PriorityCategory.COMMAND_LINE,
        null,
        Arrays.asList("--expands_by_function=no"));
    ExpansionMultipleOptions options = parser.getOptions(ExpansionMultipleOptions.class);
    assertThat(options.underlying).containsExactly("pre_value", "post_value").inOrder();
    assertThat(parser.getWarnings())
        .containsExactly(
            "option '--expands_by_function' is an expansion option. It does not accept values, "
                + "and does not change its expansion based on the value provided. "
                + "Value 'no' will be ignored.");
  }

  @Test
  public void overrideWithHigherPriority() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(NullTestOptions.class);
    parser.parse(OptionPriority.PriorityCategory.RC_FILE, null, Arrays.asList("--simple=a"));
    assertThat(parser.getOptions(NullTestOptions.class).simple).isEqualTo("a");
    parser.parse(OptionPriority.PriorityCategory.COMMAND_LINE, null, Arrays.asList("--simple=b"));
    assertThat(parser.getOptions(NullTestOptions.class).simple).isEqualTo("b");
  }

  @Test
  public void overrideWithLowerPriority() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(NullTestOptions.class);
    parser.parse(OptionPriority.PriorityCategory.COMMAND_LINE, null, Arrays.asList("--simple=a"));
    assertThat(parser.getOptions(NullTestOptions.class).simple).isEqualTo("a");
    parser.parse(OptionPriority.PriorityCategory.RC_FILE, null, Arrays.asList("--simple=b"));
    assertThat(parser.getOptions(NullTestOptions.class).simple).isEqualTo("a");
  }

  @Test
  public void getOptionValueDescriptionWithNonExistingOption() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(NullTestOptions.class);
    assertThrows(
        IllegalArgumentException.class, () -> parser.getOptionValueDescription("notexisting"));
  }

  @Test
  public void getOptionValueDescriptionWithoutValue() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(NullTestOptions.class);
    assertThat(parser.getOptionValueDescription("simple")).isNull();
  }

  @Test
  public void getOptionValueDescriptionWithValue() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(NullTestOptions.class);
    parser.parse(
        OptionPriority.PriorityCategory.COMMAND_LINE,
        "my description",
        Arrays.asList("--simple=abc"));
    OptionValueDescription result = parser.getOptionValueDescription("simple");
    assertThat(result).isNotNull();
    assertThat(result.getOptionDefinition().getOptionName()).isEqualTo("simple");
    assertThat(result.getValue()).isEqualTo("abc");
    assertThat(result.getSourceString()).isEqualTo("my description");
    assertThat(result.getCanonicalInstances()).isNotNull();
    assertThat(result.getCanonicalInstances()).hasSize(1);

    ParsedOptionDescription singleOptionInstance = result.getCanonicalInstances().get(0);
    assertThat(singleOptionInstance.getPriority().getPriorityCategory())
        .isEqualTo(OptionPriority.PriorityCategory.COMMAND_LINE);
    assertThat(singleOptionInstance.getOptionDefinition().isExpansionOption()).isFalse();
    assertThat(singleOptionInstance.getImplicitDependent()).isNull();
    assertThat(singleOptionInstance.getExpandedFrom()).isNull();
  }

  public static class ImplicitDependencyWarningOptions extends OptionsBase {
    @Option(
      name = "first",
      implicitRequirements = "--second=requiredByFirst",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "false"
    )
    public boolean first;

    @Option(
      name = "second",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null"
    )
    public String second;

    @Option(
      name = "third",
      implicitRequirements = "--second=requiredByThird",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null"
    )
    public String third;
  }

  @Test
  public void warningForImplicitOverridingExplicitOption() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(ImplicitDependencyWarningOptions.class);
    parser.parse("--second=second", "--first");
    assertThat(parser.getWarnings())
        .containsExactly(
            "option '--second' is implicitly defined by option '--first'; the implicitly set value "
                + "overrides the previous one");
  }

  @Test
  public void warningForExplicitOverridingImplicitOption() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(ImplicitDependencyWarningOptions.class);
    parser.parse("--first");
    assertThat(parser.getWarnings()).isEmpty();
    parser.parse("--second=second");
    assertThat(parser.getWarnings())
        .containsExactly(
            "A new value for option '--second' overrides a previous implicit setting of that "
                + "option by option '--first'");
  }

  @Test
  public void warningForExplicitOverridingImplicitOptionInSameCall() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(ImplicitDependencyWarningOptions.class);
    parser.parse("--first", "--second=second");
    assertThat(parser.getWarnings())
        .containsExactly(
            "A new value for option '--second' overrides a previous implicit setting of that "
                + "option by option '--first'");
  }

  @Test
  public void warningForImplicitOverridingImplicitOption() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(ImplicitDependencyWarningOptions.class);
    parser.parse("--first");
    assertThat(parser.getWarnings()).isEmpty();
    parser.parse("--third=third");
    assertThat(parser.getWarnings())
        .containsExactly(
            "option '--second' is implicitly defined by both option '--first' and "
                + "option '--third=third'");
  }

  @Test
  public void noWarningsForNonConflictingOverrides() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(ImplicitDependencyWarningOptions.class);
    parser.parse("--first", "--second=requiredByFirst");
    ImplicitDependencyWarningOptions options =
        parser.getOptions(ImplicitDependencyWarningOptions.class);
    assertThat(options.first).isTrue();
    assertThat(options.second).isEqualTo("requiredByFirst");
    assertThat(parser.getWarnings()).isEmpty();
  }

  @Test
  public void warningForImplicitRequirementsExpandedForDefaultValue() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(ImplicitDependencyWarningOptions.class);
    parser.parse("--nofirst");
    ImplicitDependencyWarningOptions options =
        parser.getOptions(ImplicitDependencyWarningOptions.class);
    assertThat(options.first).isFalse();
    assertThat(options.second).isEqualTo("requiredByFirst");
    assertThat(parser.getWarnings())
        .containsExactly(
            "--nofirst sets option '--first' to its default value. Since this option has implicit "
                + "requirements that are set whenever the option is explicitly provided, "
                + "regardless of the value, this will behave differently than letting a default "
                + "be a default. Specifically, this options expands to "
                + "{--second=requiredByFirst}.");
  }

  @Test
  public void testDependentOriginIsPropagatedToOption() throws OptionsParsingException {
    OptionsParser parser = OptionsParser.newOptionsParser(ImplicitDependencyWarningOptions.class);
    parser.parse(OptionPriority.PriorityCategory.COMMAND_LINE, null, Arrays.asList("--first"));
    OptionValueDescription first = parser.getOptionValueDescription("first");
    assertThat(first).isNotNull();
    assertThat(first.getCanonicalInstances()).hasSize(1);

    OptionValueDescription second = parser.getOptionValueDescription("second");
    assertThat(second).isNotNull();
    assertThat(second.getSourceString()).matches("implicit requirement of option '--first'");
    // Implicit requirements don't get listed as canonical. Check that this claims to be empty,
    // which tells us that the option instance is correctly tracking that is originated as an
    // implicit requirement.
    assertThat(second.getCanonicalInstances()).isNotNull();
    assertThat(second.getCanonicalInstances()).hasSize(0);
    assertThat(parser.getWarnings()).isEmpty();
  }

  /**
   * Options for testing the behavior of canonicalization when an option implicitly requires a
   * repeatable option.
   */
  public static class ImplicitDependencyOnAllowMultipleOptions extends OptionsBase {
    @Option(
      name = "first",
      implicitRequirements = "--second=requiredByFirst",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "false"
    )
    public boolean first;

    @Option(
      name = "second",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null",
      allowMultiple = true
    )
    public List<String> second;

    @Option(
      name = "third",
      implicitRequirements = "--second=requiredByThird",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null"
    )
    public String third;
  }

  @Test
  public void testCanonicalizeExcludesImplicitDependencyOnRepeatableOption()
      throws OptionsParsingException {
    OptionsParser parser =
        OptionsParser.newOptionsParser(ImplicitDependencyOnAllowMultipleOptions.class);
    parser.parse(
        OptionPriority.PriorityCategory.COMMAND_LINE,
        null,
        Arrays.asList("--first", "--second=explicitValue"));
    OptionValueDescription first = parser.getOptionValueDescription("first");
    assertThat(first).isNotNull();
    assertThat(first.getCanonicalInstances()).hasSize(1);

    OptionValueDescription second = parser.getOptionValueDescription("second");
    assertThat(second).isNotNull();
    assertThat(second.getSourceString()).matches("implicit requirement of option '--first', null");
    // Implicit requirements don't get listed as canonical. Check that this excludes the implicit
    // value, but still tracks the explicit one.
    assertThat(second.getCanonicalInstances()).isNotNull();
    assertThat(second.getCanonicalInstances()).hasSize(1);
    assertThat(parser.canonicalize()).containsExactly("--first=1", "--second=explicitValue");

    ImplicitDependencyOnAllowMultipleOptions options =
        parser.getOptions(ImplicitDependencyOnAllowMultipleOptions.class);
    assertThat(options.first).isTrue();
    assertThat(options.second).containsExactly("explicitValue", "requiredByFirst");
    assertThat(parser.getWarnings()).isEmpty();
  }

  @Test
  public void testCanonicalizeExcludesImplicitDependencyForOtherwiseUnmentionedRepeatableOption()
      throws OptionsParsingException {
    OptionsParser parser =
        OptionsParser.newOptionsParser(ImplicitDependencyOnAllowMultipleOptions.class);
    parser.parse(OptionPriority.PriorityCategory.COMMAND_LINE, null, Arrays.asList("--first"));
    OptionValueDescription first = parser.getOptionValueDescription("first");
    assertThat(first).isNotNull();
    assertThat(first.getCanonicalInstances()).hasSize(1);

    OptionValueDescription second = parser.getOptionValueDescription("second");
    assertThat(second).isNotNull();
    assertThat(second.getSourceString()).matches("implicit requirement of option '--first'");
    // Implicit requirements don't get listed as canonical. Check that this excludes the implicit
    // value, leaving behind no mention of second.
    assertThat(second.getCanonicalInstances()).isNotNull();
    assertThat(second.getCanonicalInstances()).isEmpty();
    assertThat(parser.canonicalize()).containsExactly("--first=1");

    ImplicitDependencyOnAllowMultipleOptions options =
        parser.getOptions(ImplicitDependencyOnAllowMultipleOptions.class);
    assertThat(options.first).isTrue();
    assertThat(options.second).containsExactly("requiredByFirst");
    assertThat(parser.getWarnings()).isEmpty();
  }

  public static class WarningOptions extends OptionsBase {
    @Deprecated
    @Option(
      name = "first",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null"
    )
    public Void first;

    @Deprecated
    @Option(
      name = "second",
      allowMultiple = true,
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null"
    )
    public List<String> second;

    @Deprecated
    @Option(
      name = "third",
      expansion = "--fourth=true",
      abbrev = 't',
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null"
    )
    public Void third;

    @Option(
      name = "fourth",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "false"
    )
    public boolean fourth;
  }

  @Test
  public void deprecationWarning() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(WarningOptions.class);
    parser.parse(OptionPriority.PriorityCategory.COMMAND_LINE, null, Arrays.asList("--first"));
    assertThat(parser.getWarnings()).isEqualTo(Arrays.asList("Option 'first' is deprecated"));
  }

  @Test
  public void deprecationWarningForListOption() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(WarningOptions.class);
    parser.parse(OptionPriority.PriorityCategory.COMMAND_LINE, null, Arrays.asList("--second=a"));
    assertThat(parser.getWarnings()).isEqualTo(Arrays.asList("Option 'second' is deprecated"));
  }

  @Test
  public void deprecationWarningForExpansionOption() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(WarningOptions.class);
    parser.parse(OptionPriority.PriorityCategory.COMMAND_LINE, null, Arrays.asList("--third"));
    assertThat(parser.getWarnings()).isEqualTo(Arrays.asList("Option 'third' is deprecated"));
    assertThat(parser.getOptions(WarningOptions.class).fourth).isTrue();
  }

  @Test
  public void deprecationWarningForAbbreviatedExpansionOption() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(WarningOptions.class);
    parser.parse(OptionPriority.PriorityCategory.COMMAND_LINE, null, Arrays.asList("-t"));
    assertThat(parser.getWarnings()).isEqualTo(Arrays.asList("Option 'third' is deprecated"));
    assertThat(parser.getOptions(WarningOptions.class).fourth).isTrue();
  }

  public static class NewWarningOptions extends OptionsBase {
    @Option(
      name = "first",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null",
      deprecationWarning = "it's gone"
    )
    public Void first;

    @Option(
      name = "second",
      allowMultiple = true,
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null",
      deprecationWarning = "sorry, no replacement"
    )
    public List<String> second;

    @Option(
      name = "third",
      expansion = "--fourth=true",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null",
      deprecationWarning = "use --forth instead"
    )
    public Void third;

    @Option(
      name = "fourth",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "false"
    )
    public boolean fourth;
  }

  @Test
  public void newDeprecationWarning() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(NewWarningOptions.class);
    parser.parse(OptionPriority.PriorityCategory.COMMAND_LINE, null, Arrays.asList("--first"));
    assertThat(parser.getWarnings())
        .isEqualTo(Arrays.asList("Option 'first' is deprecated: it's gone"));
  }

  @Test
  public void newDeprecationWarningForListOption() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(NewWarningOptions.class);
    parser.parse(OptionPriority.PriorityCategory.COMMAND_LINE, null, Arrays.asList("--second=a"));
    assertThat(parser.getWarnings())
        .isEqualTo(Arrays.asList("Option 'second' is deprecated: sorry, no replacement"));
  }

  @Test
  public void newDeprecationWarningForExpansionOption() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(NewWarningOptions.class);
    parser.parse(OptionPriority.PriorityCategory.COMMAND_LINE, null, Arrays.asList("--third"));
    assertThat(parser.getWarnings())
        .isEqualTo(Arrays.asList("Option 'third' is deprecated: use --forth instead"));
    assertThat(parser.getOptions(NewWarningOptions.class).fourth).isTrue();
  }

  public static class ExpansionWarningOptions extends OptionsBase {
    @Option(
      name = "first",
      expansion = "--underlying=expandedFromFirst",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null"
    )
    public Void first;

    @Option(
      name = "second",
      expansion = "--underlying=expandedFromSecond",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null"
    )
    public Void second;

    @Option(
      name = "underlying",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null"
    )
    public String underlying;
  }

  @Test
  public void warningForExpansionOverridingExplicitOption() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(ExpansionWarningOptions.class);
    parser.parse("--underlying=underlying", "--first");
    assertThat(parser.getWarnings())
        .containsExactly(
            "option '--first' was expanded and now overrides the explicit option "
                + "--underlying=underlying with --underlying=expandedFromFirst");
  }

  @Test
  public void warningForTwoConflictingExpansionOptions() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(ExpansionWarningOptions.class);
    parser.parse("--first", "--second");
    assertThat(parser.getWarnings())
        .containsExactly(
            "option '--underlying' was expanded to from both option '--first' and option "
                + "'--second'");
  }

  // This test is here to make sure that nobody accidentally changes the
  // order of the enum values and breaks the implicit assumptions elsewhere
  // in the code.
  @Test
  public void optionPrioritiesAreCorrectlyOrdered() throws Exception {
    assertThat(OptionPriority.PriorityCategory.values()).hasLength(6);
    assertThat(OptionPriority.PriorityCategory.DEFAULT)
        .isLessThan(OptionPriority.PriorityCategory.COMPUTED_DEFAULT);
    assertThat(OptionPriority.PriorityCategory.COMPUTED_DEFAULT)
        .isLessThan(OptionPriority.PriorityCategory.RC_FILE);
    assertThat(OptionPriority.PriorityCategory.RC_FILE)
        .isLessThan(OptionPriority.PriorityCategory.COMMAND_LINE);
    assertThat(OptionPriority.PriorityCategory.COMMAND_LINE)
        .isLessThan(OptionPriority.PriorityCategory.INVOCATION_POLICY);
    assertThat(OptionPriority.PriorityCategory.INVOCATION_POLICY)
        .isLessThan(OptionPriority.PriorityCategory.SOFTWARE_REQUIREMENT);
  }

  public static class IntrospectionExample extends OptionsBase {
    @Option(
      name = "alpha",
      category = "one",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "alphaDefaultValue"
    )
    public String alpha;

    @Option(
      name = "beta",
      category = "one",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "betaDefaultValue"
    )
    public String beta;

    @Option(
      name = "gamma",
      documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "gammaDefaultValue"
    )
    public String gamma;

    @Option(
      name = "delta",
      documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "deltaDefaultValue"
    )
    public String delta;

    @Option(
      name = "echo",
      metadataTags = {OptionMetadataTag.HIDDEN},
      documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "echoDefaultValue"
    )
    public String echo;
  }

  @Test
  public void asListOfUnparsedOptions() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(IntrospectionExample.class);
    parser.parse(
        OptionPriority.PriorityCategory.COMMAND_LINE,
        "source",
        Arrays.asList("--alpha=one", "--gamma=two", "--echo=three"));
    List<ParsedOptionDescription> result = parser.asCompleteListOfParsedOptions();
    assertThat(result).isNotNull();
    assertThat(result).hasSize(3);

    assertThat(result.get(0).getOptionDefinition().getOptionName()).isEqualTo("alpha");
    assertThat(result.get(0).isDocumented()).isTrue();
    assertThat(result.get(0).isHidden()).isFalse();
    assertThat(result.get(0).getUnconvertedValue()).isEqualTo("one");
    assertThat(result.get(0).getSource()).isEqualTo("source");
    assertThat(result.get(0).getPriority().getPriorityCategory())
        .isEqualTo(OptionPriority.PriorityCategory.COMMAND_LINE);

    assertThat(result.get(1).getOptionDefinition().getOptionName()).isEqualTo("gamma");
    assertThat(result.get(1).isDocumented()).isFalse();
    assertThat(result.get(1).isHidden()).isFalse();
    assertThat(result.get(1).getUnconvertedValue()).isEqualTo("two");
    assertThat(result.get(1).getSource()).isEqualTo("source");
    assertThat(result.get(1).getPriority().getPriorityCategory())
        .isEqualTo(OptionPriority.PriorityCategory.COMMAND_LINE);

    assertThat(result.get(2).getOptionDefinition().getOptionName()).isEqualTo("echo");
    assertThat(result.get(2).isDocumented()).isFalse();
    assertThat(result.get(2).isHidden()).isTrue();
    assertThat(result.get(2).getUnconvertedValue()).isEqualTo("three");
    assertThat(result.get(2).getSource()).isEqualTo("source");
    assertThat(result.get(2).getPriority().getPriorityCategory())
        .isEqualTo(OptionPriority.PriorityCategory.COMMAND_LINE);

    assertThat(parser.getWarnings()).isEmpty();
  }

  @Test
  public void asListOfExplicitOptions() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(IntrospectionExample.class);
    parser.parse(
        OptionPriority.PriorityCategory.COMMAND_LINE,
        "source",
        Arrays.asList("--alpha=one", "--gamma=two"));
    List<ParsedOptionDescription> result = parser.asListOfExplicitOptions();
    assertThat(result).isNotNull();
    assertThat(result).hasSize(2);

    assertThat(result.get(0).getOptionDefinition().getOptionName()).isEqualTo("alpha");
    assertThat(result.get(0).isDocumented()).isTrue();
    assertThat(result.get(0).getUnconvertedValue()).isEqualTo("one");
    assertThat(result.get(0).getSource()).isEqualTo("source");
    assertThat(result.get(0).getPriority().getPriorityCategory())
        .isEqualTo(OptionPriority.PriorityCategory.COMMAND_LINE);

    assertThat(result.get(1).getOptionDefinition().getOptionName()).isEqualTo("gamma");
    assertThat(result.get(1).isDocumented()).isFalse();
    assertThat(result.get(1).getUnconvertedValue()).isEqualTo("two");
    assertThat(result.get(1).getSource()).isEqualTo("source");
    assertThat(result.get(1).getPriority().getPriorityCategory())
        .isEqualTo(OptionPriority.PriorityCategory.COMMAND_LINE);

    assertThat(parser.getWarnings()).isEmpty();
  }

  private void assertOptionValue(
      String expectedName, Object expectedValue, OptionValueDescription actual) {
    assertThat(actual).isNotNull();
    assertThat(actual.getOptionDefinition().getOptionName()).isEqualTo(expectedName);
    assertThat(actual.getValue()).isEqualTo(expectedValue);
  }

  private void assertOptionValue(
      String expectedName,
      Object expectedValue,
      OptionPriority.PriorityCategory expectedPriority,
      String expectedSource,
      OptionValueDescription actual) {
    assertOptionValue(expectedName, expectedValue, actual);
    assertThat(actual.getSourceString()).isEqualTo(expectedSource);
    assertThat(actual.getCanonicalInstances()).isNotEmpty();
    assertThat(actual.getCanonicalInstances().get(0).getPriority().getPriorityCategory())
        .isEqualTo(expectedPriority);
  }

  @Test
  public void asListOfEffectiveOptions() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(IntrospectionExample.class);
    parser.parse(
        OptionPriority.PriorityCategory.COMMAND_LINE,
        "command line source",
        Arrays.asList("--alpha=alphaValueSetOnCommandLine", "--gamma=gammaValueSetOnCommandLine"));
    List<OptionValueDescription> result = parser.asListOfOptionValues();
    assertThat(result).isNotNull();
    assertThat(result).hasSize(5);
    HashMap<String,OptionValueDescription> map = new HashMap<String,OptionValueDescription>();
    for (OptionValueDescription description : result) {
      map.put(description.getOptionDefinition().getOptionName(), description);
    }

    // All options in IntrospectionExample are single-valued options, and so have a 1:1 relationship
    // with the --flag=value option instance they came from (if any).
    assertOptionValue(
        "alpha",
        "alphaValueSetOnCommandLine",
        OptionPriority.PriorityCategory.COMMAND_LINE,
        "command line source",
        map.get("alpha"));
    assertOptionValue(
        "gamma",
        "gammaValueSetOnCommandLine",
        OptionPriority.PriorityCategory.COMMAND_LINE,
        "command line source",
        map.get("gamma"));
    assertOptionValue("beta", "betaDefaultValue", map.get("beta"));
    assertOptionValue("delta", "deltaDefaultValue", map.get("delta"));
    assertOptionValue("echo", "echoDefaultValue", map.get("echo"));
    assertThat(parser.getWarnings()).isEmpty();
  }

  public static class ListExample extends OptionsBase {
    @Option(
      name = "alpha",
      converter = StringConverter.class,
      allowMultiple = true,
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null"
    )
    public List<String> alpha;
  }

  // Regression tests for bug:
  // "--option from blazerc unexpectedly overrides --option from command line"
  @Test
  public void overrideListOptions() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(ListExample.class);
    parser.parse(
        OptionPriority.PriorityCategory.COMMAND_LINE,
        "command line source",
        Arrays.asList("--alpha=cli"));
    parser.parse(
        OptionPriority.PriorityCategory.RC_FILE,
        "rc file origin",
        Arrays.asList("--alpha=rc1", "--alpha=rc2"));
    assertThat(parser.getOptions(ListExample.class).alpha)
        .isEqualTo(Arrays.asList("rc1", "rc2", "cli"));
  }

  @Test
  public void testDashDash() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(ExampleFoo.class);

    parser.parse(
        PriorityCategory.COMMAND_LINE,
        "command line source",
        Arrays.asList("--foo=woohoo", "residue", "--", "--bar=42"));

    assertThat(parser.getResidue()).hasSize(2);
    assertThat(parser.getResidue()).containsExactly("residue", "--bar=42");
    assertThat(parser.getPreDoubleDashResidue()).hasSize(1);
    assertThat(parser.getPreDoubleDashResidue()).containsExactly("residue");
  }

  @Test
  public void listOptionsHaveCorrectPriorities() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(ListExample.class);
    parser.parse(
        PriorityCategory.COMMAND_LINE,
        "command line source, part 1",
        Arrays.asList("--alpha=cli1", "--alpha=cli2"));
    parser.parse(
        PriorityCategory.COMMAND_LINE,
        "command line source, part 2",
        Arrays.asList("--alpha=cli3", "--alpha=cli4"));
    parser.parse(
        PriorityCategory.RC_FILE, "rc file origin", Arrays.asList("--alpha=rc1", "--alpha=rc2"));

    OptionValueDescription alphaValue = parser.getOptionValueDescription("alpha");

    List<ParsedOptionDescription> parsedOptions = alphaValue.getCanonicalInstances();
    System.out.println("parsedOptions:\n" + parsedOptions);

    assertThat(parsedOptions).hasSize(6);
    assertThat(parsedOptions.get(0).getSource()).matches("rc file origin");
    assertThat(parsedOptions.get(0).getUnconvertedValue()).matches("rc1");
    assertThat(parsedOptions.get(1).getSource()).matches("rc file origin");
    assertThat(parsedOptions.get(1).getUnconvertedValue()).matches("rc2");
    assertThat(parsedOptions.get(2).getSource()).matches("command line source, part 1");
    assertThat(parsedOptions.get(2).getUnconvertedValue()).matches("cli1");
    assertThat(parsedOptions.get(3).getSource()).matches("command line source, part 1");
    assertThat(parsedOptions.get(3).getUnconvertedValue()).matches("cli2");
    assertThat(parsedOptions.get(4).getSource()).matches("command line source, part 2");
    assertThat(parsedOptions.get(4).getUnconvertedValue()).matches("cli3");
    assertThat(parsedOptions.get(5).getSource()).matches("command line source, part 2");
    assertThat(parsedOptions.get(5).getUnconvertedValue()).matches("cli4");
    assertThat(parser.getWarnings()).isEmpty();
  }

  public static class CommaSeparatedOptionsExample extends OptionsBase {
    @Option(
      name = "alpha",
      converter = CommaSeparatedOptionListConverter.class,
      allowMultiple = true,
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null"
    )
    public List<String> alpha;
  }

  @Test
  public void commaSeparatedOptionsWithAllowMultiple() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(CommaSeparatedOptionsExample.class);
    parser.parse(
        OptionPriority.PriorityCategory.COMMAND_LINE,
        "command line source",
        Arrays.asList("--alpha=one", "--alpha=two,three"));
    parser.parse(
        OptionPriority.PriorityCategory.RC_FILE,
        "rc file origin",
        Arrays.asList("--alpha=rc1,rc2"));
    assertThat(parser.getOptions(CommaSeparatedOptionsExample.class).alpha)
        .isEqualTo(Arrays.asList("rc1", "rc2", "one", "two", "three"));
    assertThat(parser.getWarnings()).isEmpty();
  }

  @Test
  public void commaSeparatedListOptionsHaveCorrectPriorities() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(CommaSeparatedOptionsExample.class);
    parser.parse(
        OptionPriority.PriorityCategory.COMMAND_LINE,
        "command line source",
        Arrays.asList("--alpha=one", "--alpha=two,three"));
    parser.parse(
        OptionPriority.PriorityCategory.RC_FILE,
        "rc file origin",
        Arrays.asList("--alpha=rc1,rc2,rc3"));

    OptionValueDescription alphaValue = parser.getOptionValueDescription("alpha");
    List<ParsedOptionDescription> parsedOptions = alphaValue.getCanonicalInstances();

    assertThat(parsedOptions).hasSize(3);
    assertThat(parsedOptions.get(0).getSource()).matches("rc file origin");
    assertThat(parsedOptions.get(0).getUnconvertedValue()).matches("rc1,rc2,rc3");
    assertThat(parsedOptions.get(1).getSource()).matches("command line source");
    assertThat(parsedOptions.get(1).getUnconvertedValue()).matches("one");
    assertThat(parsedOptions.get(2).getSource()).matches("command line source");
    assertThat(parsedOptions.get(2).getUnconvertedValue()).matches("two,three");
    assertThat(parser.getWarnings()).isEmpty();
  }

  public static class Yesterday extends OptionsBase {

    @Option(
      name = "a",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "a"
    )
    public String a;

    @Option(
      name = "b",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "b"
    )
    public String b;

    @Option(
      name = "c",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null",
      expansion = {"--a=cExpansion"}
    )
    public Void c;

    @Option(
      name = "d",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null",
      allowMultiple = true
    )
    public List<String> d;

    @Option(
      name = "e",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null",
      implicitRequirements = {"--a=eRequirement"}
    )
    public String e;

    @Option(
      name = "f",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null",
      implicitRequirements = {"--b=fRequirement"}
    )
    public String f;

    @Option(
      name = "g",
      abbrev = 'h',
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "false"
    )
    public boolean g;
  }

  public static List<String> canonicalize(Class<? extends OptionsBase> optionsClass, String... args)
      throws OptionsParsingException {

    OptionsParser parser = OptionsParser.newOptionsParser(
        ImmutableList.<Class<? extends OptionsBase>>of(optionsClass));
    parser.setAllowResidue(false);
    parser.parse(Arrays.asList(args));
    return parser.canonicalize();
  }

  @Test
  public void canonicalizeEasy() throws Exception {
    assertThat(canonicalize(Yesterday.class, "--a=x")).containsExactly("--a=x");
  }

  @Test
  public void canonicalizeSkipDuplicate() throws Exception {
    assertThat(canonicalize(Yesterday.class, "--a=y", "--a=x")).containsExactly("--a=x");
  }

  @Test
  public void canonicalizeExpands() throws Exception {
    assertThat(canonicalize(Yesterday.class, "--c")).containsExactly("--a=cExpansion");
  }

  @Test
  public void canonicalizeExpansionOverridesExplicit() throws Exception {
    assertThat(canonicalize(Yesterday.class, "--a=x", "--c")).containsExactly("--a=cExpansion");
  }

  @Test
  public void canonicalizeExplicitOverridesExpansion() throws Exception {
    assertThat(canonicalize(Yesterday.class, "--c", "--a=x")).containsExactly("--a=x");
  }

  @Test
  public void canonicalizeDoesNotReorder() throws Exception {
    assertThat(canonicalize(Yesterday.class, "--b=y", "--d=x", "--a=z"))
        .containsExactly("--b=y", "--d=x", "--a=z")
        .inOrder();
  }

  @Test
  public void canonicalizeImplicitDepsNotListed() throws Exception {
    // e's requirement overrides the explicit "a" here, so the "a" value is not in the canonical
    // form - the effective value is implied and the overridden value is lost.
    assertThat(canonicalize(Yesterday.class, "--a=x", "--e=y")).containsExactly("--e=y");
  }

  @Test
  public void canonicalizeSkipsDuplicateAndStillOmmitsImplicitDeps() throws Exception {
    assertThat(canonicalize(Yesterday.class, "--e=x", "--e=y")).containsExactly("--e=y");
  }

  @Test
  public void implicitDepsAreNotInTheCanonicalOrderWhenTheyAreOverridden() throws Exception {
    assertThat(canonicalize(Yesterday.class, "--e=y", "--a=x"))
        .containsExactly("--e=y", "--a=x")
        .inOrder();
  }

  @Test
  public void implicitDepsAreNotInTheCanonicalOrder() throws Exception {
    // f requires a value of b, that is absent because it is implied.
    assertThat(canonicalize(Yesterday.class, "--f=z", "--a=x"))
        .containsExactly("--f=z", "--a=x")
        .inOrder();
  }

  @Test
  public void canonicalizeDoesNotSkipAllowMultiple() throws Exception {
    assertThat(canonicalize(Yesterday.class, "--d=a", "--d=b"))
        .containsExactly("--d=a", "--d=b").inOrder();
  }

  @Test
  public void canonicalizeReplacesAbbrevWithName() throws Exception {
    assertThat(canonicalize(Yesterday.class, "-h")).containsExactly("--g=1");
  }

  /**
   * Check that all forms of boolean flags are canonicalizes to the same form.
   *
   * The list of accepted values is from
   * {@link com.google.devtools.common.options.Converters.BooleanConverter}, and the value-less
   * --[no] form is controlled by {@link OptionsParserImpl#identifyOptionAndPossibleArgument}.
   */
  @Test
  public void canonicalizeNormalizesBooleanFlags() throws Exception {
    assertThat(canonicalize(Yesterday.class, "--g")).containsExactly("--g=1");
    assertThat(canonicalize(Yesterday.class, "--g=1")).containsExactly("--g=1");
    assertThat(canonicalize(Yesterday.class, "--g=true")).containsExactly("--g=1");
    assertThat(canonicalize(Yesterday.class, "--g=t")).containsExactly("--g=1");
    assertThat(canonicalize(Yesterday.class, "--g=yes")).containsExactly("--g=1");
    assertThat(canonicalize(Yesterday.class, "--g=y")).containsExactly("--g=1");

    assertThat(canonicalize(Yesterday.class, "--nog")).containsExactly("--g=0");
    assertThat(canonicalize(Yesterday.class, "--g=0")).containsExactly("--g=0");
    assertThat(canonicalize(Yesterday.class, "--g=false")).containsExactly("--g=0");
    assertThat(canonicalize(Yesterday.class, "--g=f")).containsExactly("--g=0");
    assertThat(canonicalize(Yesterday.class, "--g=no")).containsExactly("--g=0");
    assertThat(canonicalize(Yesterday.class, "--g=n")).containsExactly("--g=0");
  }

  public static class LongValueExample extends OptionsBase {
    @Option(
      name = "longval",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "2147483648"
    )
    public long longval;

    @Option(
      name = "intval",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "2147483647"
    )
    public int intval;
  }

  @Test
  public void parseLong() throws OptionsParsingException {
    OptionsParser parser = newOptionsParser(LongValueExample.class);
    parser.parse("");
    LongValueExample result = parser.getOptions(LongValueExample.class);
    assertThat(result.longval).isEqualTo(2147483648L);
    assertThat(result.intval).isEqualTo(2147483647);

    parser.parse("--longval", Long.toString(Long.MIN_VALUE));
    result = parser.getOptions(LongValueExample.class);
    assertThat(result.longval).isEqualTo(Long.MIN_VALUE);

    parser.parse("--longval", "100");
    result = parser.getOptions(LongValueExample.class);
    assertThat(result.longval).isEqualTo(100);
  }

  @Test
  public void intOutOfBounds() {
    OptionsParser parser = newOptionsParser(LongValueExample.class);
    OptionsParsingException e =
        assertThrows(OptionsParsingException.class, () -> parser.parse("--intval=2147483648"));
    assertThat(e).hasMessageThat().contains("'2147483648' is not an int");
  }

  public static class OldNameExample extends OptionsBase {
    @Option(
      name = "new_name",
      oldName = "old_name",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "defaultValue"
    )
    public String flag;
  }

  @Test
  public void testOldName() throws OptionsParsingException {
    OptionsParser parser = newOptionsParser(OldNameExample.class);
    parser.parse("--old_name=foo");
    OldNameExample result = parser.getOptions(OldNameExample.class);
    assertThat(result.flag).isEqualTo("foo");

    // Should also work by its new name.
    parser = newOptionsParser(OldNameExample.class);
    parser.parse("--new_name=foo");
    result = parser.getOptions(OldNameExample.class);
    assertThat(result.flag).isEqualTo("foo");
    // Should be no warnings if the new name is used.
    assertThat(parser.getWarnings()).isEmpty();
  }

  @Test
  public void testOldNameCanonicalization() throws Exception {
    assertThat(canonicalize(OldNameExample.class, "--old_name=foo"))
        .containsExactly("--new_name=foo");
  }

  public static class ExampleBooleanFooOptions extends OptionsBase {
    @Option(
      name = "foo",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "false"
    )
    public boolean foo;
  }

  @Test
  public void testBooleanUnderscorePrefixError() {
    OptionsParser parser = newOptionsParser(ExampleBooleanFooOptions.class);
    OptionsParsingException e =
        assertThrows(
            "--no_foo should fail to parse.",
            OptionsParsingException.class,
            () -> parser.parse("--no_foo"));
    assertThat(e).hasMessageThat().contains("Unrecognized option: --no_foo");
  }

  /** Dummy options that declares it uses only core types. */
  @UsesOnlyCoreTypes
  public static class CoreTypesOptions extends OptionsBase implements Serializable {
    @Option(
      name = "foo",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "false"
    )
    public boolean foo;

    @Option(
      name = "bar",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "abc"
    )
    public String bar;
  }

  /** Dummy options that does not declare using only core types. */
  public static class NonCoreTypesOptions extends OptionsBase {
    @Option(
      name = "foo",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "false"
    )
    public boolean foo;
  }

  /** Dummy options that incorrectly claims to use only core types. */
  @UsesOnlyCoreTypes
  public static class BadCoreTypesOptions extends OptionsBase {
    /** Dummy unsafe type. */
    public static class Foo {
      public int i = 0;
    }

    /** Converter for Foo. */
    public static class FooConverter implements Converter<Foo> {
      @Override
      public Foo convert(String input) throws OptionsParsingException {
        Foo foo = new Foo();
        foo.i = Integer.parseInt(input);
        return foo;
      }

      @Override
      public String getTypeDescription() {
        return "a foo";
      }
    }

    @Option(
      name = "foo",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null",
      converter = FooConverter.class
    )
    public Foo foo;
  }

  /** Dummy options that is unsafe for @UsesOnlyCoreTypes but doesn't use the annotation. */
  public static class SuperBadCoreTypesOptions extends OptionsBase {
    @Option(
      name = "foo",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "null",
      converter = BadCoreTypesOptions.FooConverter.class
    )
    public BadCoreTypesOptions.Foo foo;
  }

  /**
   * Dummy options that illegally advertises @UsesOnlyCoreTypes, when its direct fields are fine but
   * its inherited fields are not.
   */
  @UsesOnlyCoreTypes
  public static class InheritedBadCoreTypesOptions extends SuperBadCoreTypesOptions {
    @Option(
      name = "bar",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "false"
    )
    public boolean bar;
  }

  @Test
  public void testUsesOnlyCoreTypes() {
    assertThat(OptionsParser.getUsesOnlyCoreTypes(CoreTypesOptions.class)).isTrue();
    assertThat(OptionsParser.getUsesOnlyCoreTypes(NonCoreTypesOptions.class)).isFalse();
  }

  @Test
  public void testValidationOfUsesOnlyCoreTypes() {
    OptionsParser.ConstructionException expected =
        assertThrows(
            "Should have detected illegal use of @UsesOnlyCoreTypes",
            OptionsParser.ConstructionException.class,
            () -> OptionsParser.getUsesOnlyCoreTypes(BadCoreTypesOptions.class));
    assertThat(expected)
        .hasMessageThat()
        .matches(
            "Options class '.*BadCoreTypesOptions' is marked as @UsesOnlyCoreTypes, but field "
                + "'foo' has type '.*Foo'");
  }

  @Test
  public void testValidationOfUsesOnlyCoreTypes_Inherited() {
    OptionsParser.ConstructionException expected =
        assertThrows(
            "Should have detected illegal use of @UsesOnlyCoreTypes",
            OptionsParser.ConstructionException.class,
            () -> OptionsParser.getUsesOnlyCoreTypes(InheritedBadCoreTypesOptions.class));
    assertThat(expected)
        .hasMessageThat()
        .matches(
            "Options class '.*InheritedBadCoreTypesOptions' is marked as @UsesOnlyCoreTypes, but "
                + "field 'foo' has type '.*Foo'");
  }

  @Test
  public void serializable() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(CoreTypesOptions.class);
    parser.parse("--foo=true", "--bar=xyz");
    CoreTypesOptions options = parser.getOptions(CoreTypesOptions.class);

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream objOut = new ObjectOutputStream(bos);
    objOut.writeObject(options);
    objOut.flush();
    ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
    ObjectInputStream objIn = new ObjectInputStream(bis);
    Object obj = objIn.readObject();

    assertThat(obj).isEqualTo(options);
  }

  @Test
  public void stableSerialization() throws Exception {
    // Construct options two different ways to get the same result, and confirm that the serialized
    // representation is identical.
    OptionsParser parser1 = OptionsParser.newOptionsParser(CoreTypesOptions.class);
    parser1.parse("--foo=true", "--bar=xyz");
    CoreTypesOptions options1 = parser1.getOptions(CoreTypesOptions.class);
    OptionsParser parser2 = OptionsParser.newOptionsParser(CoreTypesOptions.class);
    parser2.parse("--bar=abc", "--foo=1");
    CoreTypesOptions options2 = parser2.getOptions(CoreTypesOptions.class);
    options2.bar = "xyz";

    // We use two different pairs of streams because ObjectOutputStream#reset does not actually
    // wipe all the internal state. (The first time it's used, there's an additional header that
    // does not reappear afterwards.)
    ByteArrayOutputStream bos1 = new ByteArrayOutputStream();
    ObjectOutputStream objOut1 = new ObjectOutputStream(bos1);
    objOut1.writeObject(options1);
    objOut1.flush();
    byte[] data1 = bos1.toByteArray();
    ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
    ObjectOutputStream objOut2 = new ObjectOutputStream(bos2);
    objOut2.writeObject(options2);
    objOut2.flush();
    byte[] data2 = bos2.toByteArray();

    assertThat(data1).isEqualTo(data2);
  }

  /** Dummy options for testing getHelpCompletion() and visitOptions(). */
  public static class CompletionOptions extends OptionsBase implements Serializable {
    @Option(
      name = "secret",
      documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "false"
    )
    public boolean secret;

    @Option(
        name = "b",
        documentationCategory = OptionDocumentationCategory.LOGGING,
        effectTags = {OptionEffectTag.NO_OP},
        defaultValue = "false"
      )
      public boolean b;

    @Option(
      name = "a",
      documentationCategory = OptionDocumentationCategory.QUERY,
      effectTags = {OptionEffectTag.NO_OP},
      defaultValue = "false"
    )
    public boolean a;
  }

  @Test
  public void getOptionsCompletionShouldFilterUndocumentedOptions() throws Exception {
    OptionsParser parser = OptionsParser.newOptionsParser(CompletionOptions.class);
    assertThat(parser.getOptionsCompletion().split("\n"))
        .isEqualTo(new String[] {"--a", "--noa", "--b", "--nob"});
  }

  @Test
  public void visitOptionsShouldFailWithoutPredicate() throws Exception {
    checkThatVisitOptionsThrowsNullPointerException(null, option -> {}, "Missing predicate.");
  }

  @Test
  public void visitOptionsShouldFailWithoutVisitor() throws Exception {
    checkThatVisitOptionsThrowsNullPointerException(option -> true, null, "Missing visitor.");
  }

  private void checkThatVisitOptionsThrowsNullPointerException(
      Predicate<OptionDefinition> predicate,
      Consumer<OptionDefinition> visitor,
      String expectedMessage)
      throws Exception {
    NullPointerException ex =
        assertThrows(
            NullPointerException.class,
            () ->
                OptionsParser.newOptionsParser(CompletionOptions.class)
                    .visitOptions(predicate, visitor));
    assertThat(ex).hasMessageThat().isEqualTo(expectedMessage);
  }

  @Test
  public void visitOptionsShouldReturnAllOptionsInOrder() throws Exception {
    assertThat(visitOptionsToCollectTheirNames(option -> true)).containsExactly("a", "b", "secret");
  }

  @Test
  public void visitOptionsShouldObeyPredicate() throws Exception {
    assertThat(visitOptionsToCollectTheirNames(option -> false)).isEmpty();
    assertThat(visitOptionsToCollectTheirNames(option -> option.getOptionName().length() > 1))
        .containsExactly("secret");
  }

  private List<String> visitOptionsToCollectTheirNames(Predicate<OptionDefinition> predicate) {
    List<String> names = new ArrayList<>();
    Consumer<OptionDefinition> visitor = option -> names.add(option.getOptionName());

    OptionsParser parser = OptionsParser.newOptionsParser(CompletionOptions.class);
    parser.visitOptions(predicate, visitor);

    return names;
  }
}
