// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking;

import static com.android.tools.r8.DiagnosticsChecker.checkDiagnostics;
import static com.android.tools.r8.shaking.ProguardConfigurationSourceStrings.createConfigurationForTesting;
import static org.hamcrest.core.StringContains.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.FieldAccessFlags;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.position.Position;
import com.android.tools.r8.position.TextRange;
import com.android.tools.r8.shaking.ProguardConfigurationParser.IdentifierPatternWithWildcards;
import com.android.tools.r8.utils.AbortException;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.InternalOptions.PackageObfuscationMode;
import com.android.tools.r8.utils.KeepingDiagnosticHandler;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.stream.Collectors;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

class EmptyMainClassForProguardTests {

  public static void main(String[] args) {
  }
}

public class ProguardConfigurationParserTest extends TestBase {

  private static final String VALID_PROGUARD_DIR = "src/test/proguard/valid/";
  private static final String INVALID_PROGUARD_DIR = "src/test/proguard/invalid/";
  private static final String PROGUARD_SPEC_FILE = VALID_PROGUARD_DIR + "proguard.flags";
  private static final String MULTIPLE_NAME_PATTERNS_FILE =
      VALID_PROGUARD_DIR + "multiple-name-patterns.flags";
  private static final String ACCESS_FLAGS_FILE = VALID_PROGUARD_DIR + "access-flags.flags";
  private static final String WHY_ARE_YOU_KEEPING_FILE =
      VALID_PROGUARD_DIR + "why-are-you-keeping.flags";
  private static final String ASSUME_NO_SIDE_EFFECTS =
      VALID_PROGUARD_DIR + "assume-no-side-effects.flags";
  private static final String ASSUME_NO_SIDE_EFFECTS_WITH_RETURN_VALUE =
      VALID_PROGUARD_DIR + "assume-no-side-effects-with-return-value.flags";
  private static final String ASSUME_VALUES_WITH_RETURN_VALUE =
      VALID_PROGUARD_DIR + "assume-values-with-return-value.flags";
  private static final String INCLUDING =
      VALID_PROGUARD_DIR + "including.flags";
  private static final String INVALID_INCLUDING_1 =
      INVALID_PROGUARD_DIR + "including-1.flags";
  private static final String INVALID_INCLUDING_2 =
      INVALID_PROGUARD_DIR + "including-2.flags";
  private static final String LIBRARY_JARS =
      VALID_PROGUARD_DIR + "library-jars.flags";
  private static final String LIBRARY_JARS_WIN =
      VALID_PROGUARD_DIR + "library-jars-win.flags";
  private static final String SEEDS =
      VALID_PROGUARD_DIR + "seeds.flags";
  private static final String SEEDS_2 =
      VALID_PROGUARD_DIR + "seeds-2.flags";
  private static final String VERBOSE =
      VALID_PROGUARD_DIR + "verbose.flags";
  private static final String KEEPDIRECTORIES =
      VALID_PROGUARD_DIR + "keepdirectories.flags";
  private static final String DONT_OBFUSCATE =
      VALID_PROGUARD_DIR + "dontobfuscate.flags";
  private static final String PACKAGE_OBFUSCATION_1 =
      VALID_PROGUARD_DIR + "package-obfuscation-1.flags";
  private static final String PACKAGE_OBFUSCATION_2 =
      VALID_PROGUARD_DIR + "package-obfuscation-2.flags";
  private static final String PACKAGE_OBFUSCATION_3 =
      VALID_PROGUARD_DIR + "package-obfuscation-3.flags";
  private static final String PACKAGE_OBFUSCATION_4 =
      VALID_PROGUARD_DIR + "package-obfuscation-4.flags";
  private static final String PACKAGE_OBFUSCATION_5 =
      VALID_PROGUARD_DIR + "package-obfuscation-5.flags";
  private static final String PACKAGE_OBFUSCATION_6 =
      VALID_PROGUARD_DIR + "package-obfuscation-6.flags";
  private static final String APPLY_MAPPING =
      VALID_PROGUARD_DIR + "applymapping.flags";
  private static final String APPLY_MAPPING_WITHOUT_FILE =
      INVALID_PROGUARD_DIR + "applymapping-without-file.flags";
  private static final String DONT_SHRINK =
      VALID_PROGUARD_DIR + "dontshrink.flags";
  private static final String DONT_SKIP_NON_PUBLIC_LIBRARY_CLASSES =
      VALID_PROGUARD_DIR + "dontskipnonpubliclibraryclasses.flags";
  private static final String DONT_SKIP_NON_PUBLIC_LIBRARY_CLASS_MEMBERS =
      VALID_PROGUARD_DIR + "dontskipnonpubliclibraryclassmembers.flags";
  private static final String IDENTIFIER_NAME_STRING =
      VALID_PROGUARD_DIR + "identifiernamestring.flags";
  private static final String OVERLOAD_AGGRESIVELY =
      VALID_PROGUARD_DIR + "overloadaggressively.flags";
  private static final String DONT_OPTIMIZE =
      VALID_PROGUARD_DIR + "dontoptimize.flags";
  private static final String DONT_OPTIMIZE_OVERRIDES_PASSES =
      VALID_PROGUARD_DIR + "dontoptimize-overrides-optimizationpasses.flags";
  private static final String OPTIMIZATION_PASSES =
      VALID_PROGUARD_DIR + "optimizationpasses.flags";
  private static final String OPTIMIZATION_PASSES_WITHOUT_N =
      INVALID_PROGUARD_DIR + "optimizationpasses-without-n.flags";
  private static final String PARSE_AND_SKIP_SINGLE_ARGUMENT =
      VALID_PROGUARD_DIR + "parse-and-skip-single-argument.flags";
  private static final String PRINT_USAGE =
      VALID_PROGUARD_DIR + "printusage.flags";
  private static final String PRINT_USAGE_TO_FILE =
      VALID_PROGUARD_DIR + "printusage-to-file.flags";
  private static final String TARGET =
      VALID_PROGUARD_DIR + "target.flags";

  private Reporter reporter;
  private KeepingDiagnosticHandler handler;
  private ProguardConfigurationParser parser;
  private List<String> whiteSpace =
      ImmutableList.of("", " ", "   ", "\t", " \t", " \t", " \t ", " \t\t \t ");
  private List<String> lineSeparators = ImmutableList.of("\n", "\r\n");
  private List<Character> quotes = ImmutableList.of('"', '\'');

  @Before
  public void reset() {
    handler = new KeepingDiagnosticHandler();
    reporter = new Reporter(handler);
    parser = new ProguardConfigurationParser(new DexItemFactory(), reporter);
  }

  @Before
  public void resetAllowTestOptions() {
    handler = new KeepingDiagnosticHandler();
    reporter = new Reporter(handler);
    parser = new ProguardConfigurationParser(new DexItemFactory(), reporter, true);
  }

  @Test
  public void parse() throws Exception {
    ProguardConfigurationParser parser;

    // Parse from file.
    parser = new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(PROGUARD_SPEC_FILE));
    verifyParserEndsCleanly();
    List<ProguardConfigurationRule> rules = parser.getConfig().getRules();
    assertEquals(24, rules.size());
    assertEquals(1, rules.get(0).getMemberRules().size());

    // Parse from strings.
    parser = new ProguardConfigurationParser(new DexItemFactory(), reporter);
    List<String> lines = FileUtils.readAllLines(Paths.get(PROGUARD_SPEC_FILE));
    parser.parse(createConfigurationForTesting(lines));
    rules = parser.getConfig().getRules();
    assertEquals(24, rules.size());
    assertEquals(1, rules.get(0).getMemberRules().size());
  }

  @Test
  public void parseMultipleNamePatterns() throws Exception {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(MULTIPLE_NAME_PATTERNS_FILE));
    verifyParserEndsCleanly();
    List<ProguardConfigurationRule> rules = parser.getConfig().getRules();
    assertEquals(1, rules.size());
    ProguardConfigurationRule rule = rules.get(0);
    assertEquals(1, rule.getMemberRules().size());
    assertEquals("com.company.hello.**,com.company.world.**", rule.getClassNames().toString());
    assertEquals(ProguardKeepRuleType.KEEP, ((ProguardKeepRule) rule).getType());
    assertTrue(rule.getInheritanceIsExtends());
    assertEquals("some.library.Class", rule.getInheritanceClassName().toString());
    ProguardMemberRule memberRule = rule.getMemberRules().iterator().next();
    assertTrue(memberRule.getAccessFlags().isProtected());
    assertEquals(ProguardNameMatcher.create(
        IdentifierPatternWithWildcards.withoutWildcards("getContents")), memberRule.getName());
    assertEquals("java.lang.Object[][]", memberRule.getType().toString());
    assertEquals(ProguardMemberType.METHOD, memberRule.getRuleType());
    assertEquals(0, memberRule.getArguments().size());
  }

  @Test
  public void parseNonJavaIdentifiers() throws Exception {
    DexItemFactory dexItemFactory = new DexItemFactory();
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(dexItemFactory, new Reporter());
    String nonJavaIdentifiers =
        String.join("\n", ImmutableList.of(
            "-keep class -package-.-ClassNameWithDash-{",
            "  -NameWithDash- -field-;",
            "  p-.-OtherNameWithDash- -method-(-p.-WithDash-, -package-.-ClassNameWithDash-[]); ",
            "}"));
    parser.parse(createConfigurationForTesting(ImmutableList.of(nonJavaIdentifiers)));
    verifyParserEndsCleanly();
    List<ProguardConfigurationRule> rules = parser.getConfig().getRules();
    assertEquals(1, rules.size());
    assertEquals(ProguardClassType.CLASS, rules.get(0).getClassType());
    assertEquals(1, rules.get(0).getClassNames().size());
    List<DexType> classTypes = rules.get(0).getClassNames().asSpecificDexTypes();
    assertEquals(1, classTypes.size());
    assertSame(dexItemFactory.createType("L-package-/-ClassNameWithDash-;"), classTypes.get(0));
    ProguardConfigurationRule rule = rules.get(0);
    assertEquals(2, rule.getMemberRules().size());
    int matches = 0;
    for (ProguardMemberRule memberRule : rule.getMemberRules()) {
      if (memberRule.getRuleType() == ProguardMemberType.FIELD) {
        assertTrue(memberRule.getName().matches("-field-"));
        matches |= 0x01;
      } else {
        assertEquals(ProguardMemberType.METHOD, memberRule.getRuleType());
        assertTrue(memberRule.getName().matches("-method-"));
        assertFalse(memberRule.getArguments().get(0).getSpecificType().isArrayType());
        assertSame(dexItemFactory.createType("L-p/-WithDash-;"),
            memberRule.getArguments().get(0).getSpecificType());
        assertSame(dexItemFactory.createType("[L-package-/-ClassNameWithDash-;"),
            memberRule.getArguments().get(1).getSpecificType());
        matches |= 0x02;
      }
    }
    assertEquals(0x03, matches);
  }

  private void testDontXXX(String xxx, Function<ProguardConfiguration, ProguardClassFilter> pattern)
      throws Exception {
    DexItemFactory dexItemFactory = new DexItemFactory();
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(dexItemFactory, reporter);
    String configuration = "-dont" + xxx + " !foobar,*bar";
    parser.parse(createConfigurationForTesting(ImmutableList.of(configuration)));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertFalse(pattern.apply(config).matches(dexItemFactory.createType("Lboobaz;")));
    assertTrue(pattern.apply(config).matches(dexItemFactory.createType("Lboobar;")));
    assertFalse(pattern.apply(config).matches(dexItemFactory.createType("Lfoobar;")));
  }

  @Test
  public void testDontXXX() throws Exception {
    testDontXXX("warn", ProguardConfiguration::getDontWarnPatterns);
    testDontXXX("note", ProguardConfiguration::getDontNotePatterns);
  }

  private void testDontXXXMultiple(
      String xxx, Function<ProguardConfiguration, ProguardClassFilter> pattern) throws Exception {
    DexItemFactory dexItemFactory = new DexItemFactory();
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(dexItemFactory, reporter);
    List<String> configuration1 = ImmutableList.of("-dont" + xxx + " foo.**, bar.**");
    List<String> configuration2 = ImmutableList.of("-dont" + xxx + " foo.**", "-dontwarn bar.**");
    for (List<String> configuration : ImmutableList.of(configuration1, configuration2)) {
      parser.parse(createConfigurationForTesting(configuration));
      verifyParserEndsCleanly();
      ProguardConfiguration config = parser.getConfig();
      assertTrue(pattern.apply(config).matches(dexItemFactory.createType("Lfoo/Bar;")));
      assertTrue(pattern.apply(config).matches(dexItemFactory.createType("Lfoo/bar7Bar;")));
      assertTrue(pattern.apply(config).matches(dexItemFactory.createType("Lbar/Foo;")));
    }
  }

  @Test
  public void testDontWarnMultiple() throws Exception {
    testDontXXXMultiple("warn", ProguardConfiguration::getDontWarnPatterns);
    testDontXXXMultiple("note", ProguardConfiguration::getDontNotePatterns);
  }

  private void testDontXXXAllExplicitly(
      String xxx, Function<ProguardConfiguration, ProguardClassFilter> pattern) throws Exception {
    DexItemFactory dexItemFactory = new DexItemFactory();
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(dexItemFactory, reporter);
    String dontwarnAll = "-dont" + xxx + " *";
    parser.parse(createConfigurationForTesting(ImmutableList.of(dontwarnAll)));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(pattern.apply(config).matches(dexItemFactory.createType("Lboobaz;")));
    assertTrue(pattern.apply(config).matches(dexItemFactory.createType("Lboobar;")));
    assertTrue(pattern.apply(config).matches(dexItemFactory.createType("Lfoobar;")));
  }

  @Test
  public void testDontWarnAllExplicitly() throws Exception {
    testDontXXXAllExplicitly("warn", ProguardConfiguration::getDontWarnPatterns);
    testDontXXXAllExplicitly("note", ProguardConfiguration::getDontNotePatterns);
  }

  private void testDontXXXAllImplicitly(
      String xxx, Function<ProguardConfiguration, ProguardClassFilter> pattern) throws Exception {
    DexItemFactory dexItemFactory = new DexItemFactory();
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(dexItemFactory, reporter);
    String dontwarnAll = "-dont" + xxx;
    String otherOption = "-keep class *";
    parser.parse(createConfigurationForTesting(ImmutableList.of(dontwarnAll, otherOption)));
    ProguardConfiguration config = parser.getConfig();
    assertTrue(pattern.apply(config).matches(dexItemFactory.createType("Lboobaz;")));
    assertTrue(pattern.apply(config).matches(dexItemFactory.createType("Lboobar;")));
    assertTrue(pattern.apply(config).matches(dexItemFactory.createType("Lfoobar;")));
  }

  @Test
  public void testDontWarnAllImplicitly() throws Exception {
    testDontXXXAllImplicitly("warn", ProguardConfiguration::getDontWarnPatterns);
    testDontXXXAllImplicitly("note", ProguardConfiguration::getDontNotePatterns);
  }

  @Test
  public void parseAccessFlags() throws Exception {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(ACCESS_FLAGS_FILE));
    verifyParserEndsCleanly();
    List<ProguardConfigurationRule> rules = parser.getConfig().getRules();
    assertEquals(1, rules.size());
    ProguardConfigurationRule rule = rules.get(0);
    ClassAccessFlags publicAndFinalFlags = ClassAccessFlags.fromSharedAccessFlags(0);
    publicAndFinalFlags.setPublic();
    publicAndFinalFlags.setFinal();
    assertTrue(rule.getClassAccessFlags().containsNone(publicAndFinalFlags));
    assertTrue(rule.getNegatedClassAccessFlags().containsAll(publicAndFinalFlags));
    ClassAccessFlags abstractFlags = ClassAccessFlags.fromSharedAccessFlags(0);
    abstractFlags.setAbstract();
    assertTrue(rule.getClassAccessFlags().containsAll(abstractFlags));
    assertTrue(rule.getNegatedClassAccessFlags().containsNone(abstractFlags));
    for (ProguardMemberRule member : rule.getMemberRules()) {
      if (member.getRuleType() == ProguardMemberType.ALL_FIELDS) {
        FieldAccessFlags publicFlags = FieldAccessFlags.fromSharedAccessFlags(0);
        publicFlags.setPublic();
        assertTrue(member.getAccessFlags().containsAll(publicFlags));
        assertTrue(member.getNegatedAccessFlags().containsNone(publicFlags));
        FieldAccessFlags staticFlags = FieldAccessFlags.fromSharedAccessFlags(0);
        staticFlags.setStatic();
        assertTrue(member.getAccessFlags().containsNone(staticFlags));
        assertTrue(member.getNegatedAccessFlags().containsAll(staticFlags));
      } else {
        assertTrue(member.getRuleType() == ProguardMemberType.ALL_METHODS);

        MethodAccessFlags publicNativeFlags = MethodAccessFlags.fromSharedAccessFlags(0, false);
        publicNativeFlags.setPublic();
        publicNativeFlags.setNative();
        assertTrue(member.getAccessFlags().containsAll(publicNativeFlags));
        assertFalse(member.getNegatedAccessFlags().containsNone(publicNativeFlags));

        MethodAccessFlags protectedNativeFlags = MethodAccessFlags.fromSharedAccessFlags(0, false);
        protectedNativeFlags.setProtected();
        protectedNativeFlags.setNative();
        assertTrue(member.getAccessFlags().containsAll(protectedNativeFlags));
        assertFalse(member.getNegatedAccessFlags().containsNone(protectedNativeFlags));
      }
    }
  }

  @Test
  public void parseWhyAreYouKeeping() throws Exception {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(WHY_ARE_YOU_KEEPING_FILE));
    verifyParserEndsCleanly();
    List<ProguardConfigurationRule> rules = parser.getConfig().getRules();
    assertEquals(1, rules.size());
    ProguardConfigurationRule rule = rules.get(0);
    assertEquals(1, rule.getClassNames().size());
    assertEquals("*", rule.getClassNames().toString());
    assertTrue(rule.getInheritanceIsExtends());
    assertEquals("foo.bar", rule.getInheritanceClassName().toString());
  }

  @Test
  public void parseAssumeNoSideEffects() throws Exception {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(ASSUME_NO_SIDE_EFFECTS));
    verifyParserEndsCleanly();
    List<ProguardConfigurationRule> assumeNoSideEffects = parser.getConfig().getRules();
    assertEquals(1, assumeNoSideEffects.size());
    assumeNoSideEffects.get(0).getMemberRules().forEach(rule -> {
      assertFalse(rule.hasReturnValue());
    });
  }

  @Test
  public void parseAssumeNoSideEffectsWithReturnValue() throws Exception {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(ASSUME_NO_SIDE_EFFECTS_WITH_RETURN_VALUE));
    verifyParserEndsCleanly();
    List<ProguardConfigurationRule> assumeNoSideEffects = parser.getConfig().getRules();
    assertEquals(1, assumeNoSideEffects.size());
    int matches = 0;
    for (ProguardMemberRule rule : assumeNoSideEffects.get(0).getMemberRules()) {
      assertTrue(rule.hasReturnValue());
      if (rule.getName().matches("returnsTrue") || rule.getName().matches("returnsFalse")) {
        assertTrue(rule.getReturnValue().isBoolean());
        assertFalse(rule.getReturnValue().isValueRange());
        assertFalse(rule.getReturnValue().isField());
        assertFalse(rule.getReturnValue().isNull());
        assertEquals(rule.getName().matches("returnsTrue"), rule.getReturnValue().getBoolean());
        matches |= 1 << 0;
      } else if (rule.getName().matches("returns1")) {
        assertFalse(rule.getReturnValue().isBoolean());
        assertTrue(rule.getReturnValue().isValueRange());
        assertFalse(rule.getReturnValue().isField());
        assertFalse(rule.getReturnValue().isNull());
        assertTrue(rule.getReturnValue().isSingleValue());
        assertEquals(1, rule.getReturnValue().getValueRange().getMin());
        assertEquals(1, rule.getReturnValue().getValueRange().getMax());
        assertEquals(1, rule.getReturnValue().getSingleValue());
        matches |= 1 << 1;
      } else if (rule.getName().matches("returns2To4")) {
        assertFalse(rule.getReturnValue().isBoolean());
        assertTrue(rule.getReturnValue().isValueRange());
        assertFalse(rule.getReturnValue().isField());
        assertFalse(rule.getReturnValue().isNull());
        assertFalse(rule.getReturnValue().isSingleValue());
        assertEquals(2, rule.getReturnValue().getValueRange().getMin());
        assertEquals(4, rule.getReturnValue().getValueRange().getMax());
        matches |= 1 << 2;
      } else if (rule.getName().matches("returns234To567")) {
        assertFalse(rule.getReturnValue().isBoolean());
        assertTrue(rule.getReturnValue().isValueRange());
        assertFalse(rule.getReturnValue().isField());
        assertFalse(rule.getReturnValue().isNull());
        assertFalse(rule.getReturnValue().isSingleValue());
        assertEquals(234, rule.getReturnValue().getValueRange().getMin());
        assertEquals(567, rule.getReturnValue().getValueRange().getMax());
        matches |= 1 << 3;
      } else if (rule.getName().matches("returnsField")) {
        assertFalse(rule.getReturnValue().isBoolean());
        assertFalse(rule.getReturnValue().isValueRange());
        assertTrue(rule.getReturnValue().isField());
        assertFalse(rule.getReturnValue().isNull());
        assertEquals("com.google.C", rule.getReturnValue().getField().holder.toString());
        assertEquals("int", rule.getReturnValue().getField().type.toString());
        assertEquals("X", rule.getReturnValue().getField().name.toString());
        matches |= 1 << 4;
      } else if (rule.getName().matches("returnsNull")) {
        assertFalse(rule.getReturnValue().isBoolean());
        assertFalse(rule.getReturnValue().isValueRange());
        assertFalse(rule.getReturnValue().isField());
        assertTrue(rule.getReturnValue().isNull());
        assertTrue(rule.getReturnValue().isSingleValue());
        matches |= 1 << 5;
      } else {
        fail("Unexpected");
      }
    }
    assertEquals((1 << 6) - 1, matches);
  }

  @Test
  public void parseAssumeValuesWithReturnValue() throws Exception {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(ASSUME_VALUES_WITH_RETURN_VALUE));
    verifyParserEndsCleanly();
    List<ProguardConfigurationRule> assumeValues = parser.getConfig().getRules();
    assertEquals(1, assumeValues.size());
    int matches = 0;
    for (ProguardMemberRule rule : assumeValues.get(0).getMemberRules()) {
      assertTrue(rule.hasReturnValue());
      if (rule.getName().matches("isTrue") || rule.getName().matches("isFalse")) {
        assertTrue(rule.getReturnValue().isBoolean());
        assertFalse(rule.getReturnValue().isValueRange());
        assertFalse(rule.getReturnValue().isField());
        assertFalse(rule.getReturnValue().isNull());
        assertEquals(rule.getName().matches("isTrue"), rule.getReturnValue().getBoolean());
        matches |= 1 << 0;
      } else if (rule.getName().matches("is1")) {
        assertFalse(rule.getReturnValue().isBoolean());
        assertTrue(rule.getReturnValue().isValueRange());
        assertFalse(rule.getReturnValue().isField());
        assertFalse(rule.getReturnValue().isNull());
        assertTrue(rule.getReturnValue().isSingleValue());
        assertEquals(1, rule.getReturnValue().getValueRange().getMin());
        assertEquals(1, rule.getReturnValue().getValueRange().getMax());
        assertEquals(1, rule.getReturnValue().getSingleValue());
        matches |= 1 << 1;
      } else if (rule.getName().matches("is2To4")) {
        assertFalse(rule.getReturnValue().isBoolean());
        assertTrue(rule.getReturnValue().isValueRange());
        assertFalse(rule.getReturnValue().isField());
        assertFalse(rule.getReturnValue().isNull());
        assertFalse(rule.getReturnValue().isSingleValue());
        assertEquals(2, rule.getReturnValue().getValueRange().getMin());
        assertEquals(4, rule.getReturnValue().getValueRange().getMax());
        matches |= 1 << 2;
      } else if (rule.getName().matches("is234To567")) {
        assertFalse(rule.getReturnValue().isBoolean());
        assertTrue(rule.getReturnValue().isValueRange());
        assertFalse(rule.getReturnValue().isField());
        assertFalse(rule.getReturnValue().isNull());
        assertFalse(rule.getReturnValue().isSingleValue());
        assertEquals(234, rule.getReturnValue().getValueRange().getMin());
        assertEquals(567, rule.getReturnValue().getValueRange().getMax());
        matches |= 1 << 3;
      } else if (rule.getName().matches("isField")) {
        assertFalse(rule.getReturnValue().isBoolean());
        assertFalse(rule.getReturnValue().isValueRange());
        assertTrue(rule.getReturnValue().isField());
        assertFalse(rule.getReturnValue().isNull());
        assertEquals("com.google.C", rule.getReturnValue().getField().holder.toString());
        assertEquals("int", rule.getReturnValue().getField().type.toString());
        assertEquals("X", rule.getReturnValue().getField().name.toString());
        matches |= 1 << 4;
      } else if (rule.getName().matches("isNull")) {
        assertFalse(rule.getReturnValue().isBoolean());
        assertFalse(rule.getReturnValue().isValueRange());
        assertFalse(rule.getReturnValue().isField());
        assertTrue(rule.getReturnValue().isNull());
        assertTrue(rule.getReturnValue().isSingleValue());
        matches |= 1 << 5;
      } else {
        fail("Unexpected");
      }
    }
    assertEquals((1 << 6) - 1, matches);
  }

  @Test
  public void testAdaptClassStrings() throws Exception {
    DexItemFactory dexItemFactory = new DexItemFactory();
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(dexItemFactory, reporter);
    String adaptClassStrings = "-adaptclassstrings !foobar,*bar";
    parser.parse(createConfigurationForTesting(ImmutableList.of(adaptClassStrings)));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertFalse(
        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobaz;")));
    assertTrue(
        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobar;")));
    assertFalse(
        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lfoobar;")));
  }

  @Test
  public void testAdaptClassStringsMultiple() throws Exception {
    DexItemFactory dexItemFactory = new DexItemFactory();
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(dexItemFactory, reporter);
    List<String> configuration1 = ImmutableList.of("-adaptclassstrings foo.**, bar.**");
    List<String> configuration2 =
        ImmutableList.of("-adaptclassstrings foo.**", "-adaptclassstrings bar.**");
    for (List<String> configuration : ImmutableList.of(configuration1, configuration2)) {
      parser.parse(createConfigurationForTesting(configuration));
      verifyParserEndsCleanly();
      ProguardConfiguration config = parser.getConfig();
      assertTrue(
          config.getAdaptClassStrings().matches(dexItemFactory.createType("Lfoo/Bar;")));
      assertTrue(
          config.getAdaptClassStrings().matches(dexItemFactory.createType("Lfoo/bar7Bar;")));
      assertTrue(
          config.getAdaptClassStrings().matches(dexItemFactory.createType("Lbar/Foo;")));
    }
  }

  @Test
  public void testAdaptClassStringsAllExplicitly() throws Exception {
    DexItemFactory dexItemFactory = new DexItemFactory();
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(dexItemFactory, reporter);
    String adaptAll = "-adaptclassstrings *";
    parser.parse(createConfigurationForTesting(ImmutableList.of(adaptAll)));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(
        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobaz;")));
    assertTrue(
        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobar;")));
    assertTrue(
        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lfoobar;")));
  }

  @Test
  public void testAdaptClassStringsAllImplicitly() throws Exception {
    DexItemFactory dexItemFactory = new DexItemFactory();
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(dexItemFactory, reporter);
    String adaptAll = "-adaptclassstrings";
    parser.parse(createConfigurationForTesting(ImmutableList.of(adaptAll)));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(
        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobaz;")));
    assertTrue(
        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobar;")));
    assertTrue(
        config.getAdaptClassStrings().matches(dexItemFactory.createType("Lfoobar;")));
  }

  @Test
  public void testIdentifierNameString() throws Exception {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    String config1 =
        "-identifiernamestring class a.b.c.*GeneratedClass {\n"
        + "  static java.lang.String CONTAINING_TYPE_*;\n"
        + "}";
    String config2 =
        "-identifiernamestring class x.y.z.ReflectionBasedFactory {\n"
        + "  private static java.lang.reflect.Field field(java.lang.Class,java.lang.String);\n"
        + "}";
    String config3 =
        "-identifiernamestring class * {\n"
        + "  @my.annotations.IdentifierNameString *;\n"
        + "}";
    parser.parse(createConfigurationForTesting(ImmutableList.of(config1, config2, config3)));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    List<ProguardConfigurationRule> identifierNameStrings = config.getRules();
    assertEquals(3, identifierNameStrings.size());
    assertEquals(1, identifierNameStrings.get(0).getClassNames().size());
    assertEquals(
        "a.b.c.*GeneratedClass",
        identifierNameStrings.get(0).getClassNames().toString());
    identifierNameStrings.get(0).getMemberRules().forEach(memberRule -> {
      assertTrue(memberRule.getRuleType().includesFields());
      assertTrue(memberRule.getName().matches("CONTAINING_TYPE_ABC"));
    });
    assertEquals(1, identifierNameStrings.get(1).getClassNames().size());
    assertEquals(
        "x.y.z.ReflectionBasedFactory",
        identifierNameStrings.get(1).getClassNames().toString());
    identifierNameStrings.get(1).getMemberRules().forEach(memberRule -> {
      assertTrue(memberRule.getRuleType().includesMethods());
      assertTrue(memberRule.getName().matches("field"));
    });
    assertEquals(1, identifierNameStrings.get(2).getClassNames().size());
    assertEquals("*", identifierNameStrings.get(2).getClassNames().toString());
    identifierNameStrings.get(2).getMemberRules().forEach(memberRule -> {
      assertEquals(ProguardMemberType.ALL, memberRule.getRuleType());
      assertTrue(memberRule.getAnnotation().toString().endsWith("IdentifierNameString"));
    });
  }

  @Test
  public void parseDontobfuscate() throws Exception {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(DONT_OBFUSCATE));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertFalse(config.isObfuscating());
  }

  @Test
  public void parseRepackageClassesEmpty() throws Exception {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(PACKAGE_OBFUSCATION_1));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertEquals(PackageObfuscationMode.REPACKAGE, config.getPackageObfuscationMode());
    assertNotNull(config.getPackagePrefix());
    assertEquals("", config.getPackagePrefix());
  }

  @Test
  public void parseRepackageClassesNonEmpty() throws Exception {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(PACKAGE_OBFUSCATION_2));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertEquals(PackageObfuscationMode.REPACKAGE, config.getPackageObfuscationMode());
    assertNotNull(config.getPackagePrefix());
    assertEquals("p.q.r", config.getPackagePrefix());
  }

  @Test
  public void parseFlattenPackageHierarchyEmpty() throws Exception {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(PACKAGE_OBFUSCATION_3));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertEquals(PackageObfuscationMode.FLATTEN, config.getPackageObfuscationMode());
    assertNotNull(config.getPackagePrefix());
    assertEquals("", config.getPackagePrefix());
  }

  @Test
  public void parseFlattenPackageHierarchyNonEmpty() throws Exception {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(PACKAGE_OBFUSCATION_4));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertEquals(PackageObfuscationMode.FLATTEN, config.getPackageObfuscationMode());
    assertNotNull(config.getPackagePrefix());
    assertEquals("p.q.r", config.getPackagePrefix());
  }

  @Test
  public void flattenPackageHierarchyCannotOverrideRepackageClasses() throws Exception {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    Path path = Paths.get(PACKAGE_OBFUSCATION_5);
    parser.parse(path);
    checkDiagnostics(handler.warnings, path, 6, 1,
        "repackageclasses", "overrides", "flattenpackagehierarchy");
    ProguardConfiguration config = parser.getConfig();
    assertEquals(PackageObfuscationMode.REPACKAGE, config.getPackageObfuscationMode());
    assertNotNull(config.getPackagePrefix());
    assertEquals("top", config.getPackagePrefix());
  }

  @Test
  public void repackageClassesOverridesFlattenPackageHierarchy() throws Exception {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    Path path = Paths.get(PACKAGE_OBFUSCATION_6);
    parser.parse(path);
    checkDiagnostics(handler.warnings, path, 6, 1,
        "repackageclasses", "overrides", "flattenpackagehierarchy");
    ProguardConfiguration config = parser.getConfig();
    assertEquals(PackageObfuscationMode.REPACKAGE, config.getPackageObfuscationMode());
    assertNotNull(config.getPackagePrefix());
    assertEquals("top", config.getPackagePrefix());
  }

  @Test
  public void parseApplyMapping() throws Exception {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(APPLY_MAPPING));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(config.hasApplyMappingFile());
  }

  @Test
  public void parseApplyMappingWithoutFile() throws Exception {
    Path path = Paths.get(APPLY_MAPPING_WITHOUT_FILE);
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(path);
      fail("Expect to fail due to the lack of file name.");
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, path, 6, 14, "File name expected");
    }
  }

  @Test
  public void parseIncluding() throws Exception {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(INCLUDING));
    verifyParserEndsCleanly();
  }

  @Test
  public void parseInvalidIncluding1() throws IOException {
    Path path = Paths.get(INVALID_INCLUDING_1);
    try {
      new ProguardConfigurationParser(new DexItemFactory(), reporter)
          .parse(path);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, path, 6, 10,"does-not-exist.flags");
    }
  }

  @Test
  public void parseInvalidIncluding2() {
    Path path = Paths.get(INVALID_INCLUDING_2);
    try {
      new ProguardConfigurationParser(new DexItemFactory(), reporter)
          .parse(path);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, path, 6,2, "does-not-exist.flags");
    }
  }

  @Test
  public void parseLibraryJars() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    if (!ToolHelper.isLinux() && !ToolHelper.isMac()) {
      parser.parse(Paths.get(LIBRARY_JARS_WIN));
    } else {
      parser.parse(Paths.get(LIBRARY_JARS));
    }
    assertEquals(4, parser.getConfig().getLibraryjars().size());
  }

  @Test
  public void parseInvalidFilePattern() {
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(createConfigurationForTesting(
          Collections.singletonList("-injars abc.jar(*.zip;*.class)")));
      fail();
    } catch (AbortException e) {
      assertEquals(1, handler.errors.size());
    }
  }

  @Test
  public void parseKeepModifiers() {
    for (String before : whiteSpace) {
      for (String after : whiteSpace) {
        reset();
        parseAndVerifyParserEndsCleanly(ImmutableList.of(
            "-keep"
                + before + "," + after + "includedescriptorclasses"
                + before + "," + after + "allowshrinking"
                + before + "," + after + "allowobfuscation"
                + before + "," + after + "allowoptimization "
                + "class A { *; }"
        ));
      }
    }
  }

  @Test
  public void parseKeepAnnotation() {
    for (String space : whiteSpace) {
      reset();
      parseAndVerifyParserEndsCleanly(ImmutableList.of(
          "-keep @" + space + "interface A"
      ));
    }
  }

  @Test
  public void regress78442725() {
    parseAndVerifyParserEndsCleanly(ImmutableList.of(
        "-keep, includedescriptorclasses class in.uncod.android.bypass.Document { *; }",
        "-keep, includedescriptorclasses class in.uncod.android.bypass.Element { *; }"
    ));
  }

  @Test
  public void parseSeeds() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(SEEDS));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(config.isPrintSeeds());
    assertNull(config.getSeedFile());
  }

  @Test
  public void parseSeeds2() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(SEEDS_2));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(config.isPrintSeeds());
    assertNotNull(config.getSeedFile());
  }

  @Test
  public void parseVerbose() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(VERBOSE));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(config.isVerbose());
  }

  @Test
  public void parseKeepdirectories() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter, false);
    parser.parse(Paths.get(KEEPDIRECTORIES));
    verifyParserEndsCleanly();
  }

  @Test
  public void parseDontshrink() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(DONT_SHRINK));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertFalse(config.isShrinking());
  }

  @Test
  public void parseDontSkipNonPublicLibraryClasses() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(DONT_SKIP_NON_PUBLIC_LIBRARY_CLASSES));
    verifyParserEndsCleanly();
  }

  @Test
  public void parseDontskipnonpubliclibraryclassmembers() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(DONT_SKIP_NON_PUBLIC_LIBRARY_CLASS_MEMBERS));
    verifyParserEndsCleanly();
  }

  @Test
  public void parseIdentifiernamestring() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    Path source = Paths.get(IDENTIFIER_NAME_STRING);
    parser.parse(source);
    verifyParserEndsCleanly();
  }

  @Test
  public void parseOverloadAggressively() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(OVERLOAD_AGGRESIVELY));
    verifyParserEndsCleanly();
  }

  @Test
  public void parseDontOptimize() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(DONT_OPTIMIZE));
    ProguardConfiguration config = parser.getConfig();
    verifyParserEndsCleanly();
    assertFalse(config.isOptimizing());
  }

  @Test
  public void parseDontOptimizeOverridesPasses() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    Path path = Paths.get(DONT_OPTIMIZE_OVERRIDES_PASSES);
    parser.parse(path);
    checkDiagnostics(handler.infos, path, 7, 1, "Ignoring", "-optimizationpasses");
    ProguardConfiguration config = parser.getConfig();
    assertFalse(config.isOptimizing());
  }

  @Test
  public void parseOptimizationPasses() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    Path path = Paths.get(OPTIMIZATION_PASSES);
    parser.parse(path);
    checkDiagnostics(handler.infos, path, 5, 1, "Ignoring", "-optimizationpasses");
    ProguardConfiguration config = parser.getConfig();
    assertTrue(config.isOptimizing());
  }

  @Test
  public void parseOptimizationPassesError() {
    Path path = Paths.get(OPTIMIZATION_PASSES_WITHOUT_N);
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(path);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, path, 6, 1, "Missing n");
    }
  }

  @Test
  public void parseSkipNonPublicLibraryClasses() {
    testUnsupportedOption("-skipnonpubliclibraryclasses");
  }

  private void testUnsupportedOption(String option) {
    try {
      reset();
      parser.parse(createConfigurationForTesting(ImmutableList.of(option)));
      fail("Expect to fail due to unsupported option.");
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, null, 1, 1, "Unsupported option", option);
    }
  }

  @Test
  public void parseAndskipSingleArgument() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(PARSE_AND_SKIP_SINGLE_ARGUMENT));
    verifyParserEndsCleanly();
  }

  @Test
  public void parse_printconfiguration_noArguments() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(createConfigurationForTesting(ImmutableList.of(
        "-printconfiguration"
    )));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(config.isPrintConfiguration());
    assertNull(config.getPrintConfigurationFile());
  }

  @Test
  public void parse_printconfiguration_argument() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(createConfigurationForTesting(ImmutableList.of(
        "-printconfiguration file_name"
    )));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(config.isPrintConfiguration());
    assertEquals("file_name", config.getPrintConfigurationFile().toString());
  }

  @Test
  public void parse_optimizations() throws Exception {
    for (String option :
        ImmutableList.of(
            "-optimizations",
            "-optimizations xxx",
            "-optimizations     xxx",
            "-optimizations xxx/yyy",
            "-optimizations     xxx/yyy",
            "-optimizations xxx/yyy,zzz*",
            "-optimizations xxx/yyy  ,  zzz*",
            "-optimizations !xxx",
            "-optimizations   !  xxx",
            "-optimizations !xxx,!yyy",
            "-optimizations   !  xxx,  !  yyy",
            "-optimizations !code/simplification/advanced,code/simplification/*")) {
      reset();
      Path proguardConfig = writeTextToTempFile(option);
      parser.parse(proguardConfig);
      assertEquals(1, handler.infos.size());
      checkDiagnostics(handler.infos, proguardConfig, 1, 1, "Ignoring", "-optimizations");
    }
  }

  @Test
  public void parse_optimizationpasses() throws Exception {
    for (String lineSeparator : lineSeparators) {
      reset();
      Path proguardConfig = writeTextToTempFile(lineSeparator,
          ImmutableList.of(
              "-optimizations xxx",
              "-optimizationpasses 5",
              "-optimizations yyy"));
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      assertEquals(3, handler.infos.size());

      checkDiagnostics(handler.infos, 0, proguardConfig, 1, 1, "Ignoring", "-optimizations");
      Position p1 = handler.infos.get(0).getPosition();
      assertTrue(p1 instanceof TextRange);
      TextRange r1 = (TextRange) p1;
      assertEquals(1, r1.getStart().getLine());
      assertEquals(1, r1.getStart().getColumn());
      assertEquals(1, r1.getEnd().getLine());
      assertEquals(15, r1.getEnd().getColumn());

      checkDiagnostics(
          handler.infos, 1, proguardConfig, 2, 1, "Ignoring", "-optimizationpasses");
      Position p2 = handler.infos.get(1).getPosition();
      assertTrue(p2 instanceof TextRange);
      TextRange r2 = (TextRange) p2;
      assertEquals(2, r2.getStart().getLine());
      assertEquals(1, r2.getStart().getColumn());
      assertEquals(2, r2.getEnd().getLine());
      assertEquals(22, r2.getEnd().getColumn());

      checkDiagnostics(handler.infos, 2, proguardConfig, 3, 1, "Ignoring", "-optimizations");
      Position p3 = handler.infos.get(2).getPosition();
      assertTrue(p3 instanceof TextRange);
      TextRange r3 = (TextRange) p3;
      assertEquals(3, r3.getStart().getLine());
      assertEquals(1, r3.getStart().getColumn());
      assertEquals(3, r3.getEnd().getLine());
      assertEquals(15, r3.getEnd().getColumn());
    }
  }

  @Test
  public void parsePrintUsage() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(PRINT_USAGE));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(config.isPrintUsage());
    assertNull(config.getPrintUsageFile());
  }

  @Test
  public void parsePrintUsageToFile() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(PRINT_USAGE_TO_FILE));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(config.isPrintUsage());
    assertNotNull(config.getPrintUsageFile());
  }

  @Test
  public void parseTarget() {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(Paths.get(TARGET));
    verifyParserEndsCleanly();
  }

  @Test
  public void parseInvalidKeepOption() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-keepx public class * {       ",
        "  native <methods>;           ",
        "}                             "
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 1, 1,
          "Unknown option", "-keepx");
    }
  }

  @Test
  public void parseKeepOptionEOF() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        System.lineSeparator(), ImmutableList.of("-keep"), false);
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 1, 6,
          "Expected [!]interface|@interface|class|enum");
    }
  }

  @Test
  public void parseInvalidKeepClassOption() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-keepclassx public class * {  ",
        "  native <methods>;           ",
        "}                             "
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 1, 1,
          "Unknown option", "-keepclassx");
    }
  }

  @Test
  public void parseCustomFlags() throws Exception {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    // Custom Proguard flags -runtype and -laststageoutput are ignored.
    Path proguardConfig = writeTextToTempFile(
        "-runtype FINAL                    ",
        "-laststageoutput /some/file/name  "
    );
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();
  }

  @Test
  public void testRenameSourceFileAttribute() throws Exception {
    for (String lineSeparator : lineSeparators) {
      reset();
      Path proguardConfig = writeTextToTempFile(lineSeparator,
          ImmutableList.of(
              "-renamesourcefileattribute PG",
              "-keepattributes SourceFile,SourceDir"));
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      verifyParserEndsCleanly();
      ProguardConfiguration config = parser.getConfigRawForTesting();
      assertEquals("PG", config.getRenameSourceFileAttribute());
      assertTrue(config.getKeepAttributes().sourceFile);
      assertTrue(config.getKeepAttributes().sourceDir);
    }
  }

  @Test
  public void testRenameSourceFileAttribute_empty() throws Exception {
    for (String lineSeparator : lineSeparators) {
      reset();
      Path proguardConfig = writeTextToTempFile(lineSeparator,
          ImmutableList.of(
              "-renamesourcefileattribute",
              "-keepattributes SourceFile"));
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      verifyParserEndsCleanly();
      ProguardConfiguration config = parser.getConfigRawForTesting();
      assertEquals("", config.getRenameSourceFileAttribute());
      assertTrue(config.getKeepAttributes().sourceFile);
      assertFalse(config.getKeepAttributes().sourceDir);
    }
  }

  @Test
  public void testRenameSourceFileAttribute_qouted() throws Exception {
    for (String lineSeparator : lineSeparators) {
      for (Character quote : quotes) {
        reset();
        Path proguardConfig = writeTextToTempFile(lineSeparator,
            ImmutableList.of(
                "-renamesourcefileattribute " + quote + "PG" + quote,
                "-keepattributes SourceFile"));
        ProguardConfigurationParser parser =
            new ProguardConfigurationParser(new DexItemFactory(), reporter);
        parser.parse(proguardConfig);
        verifyParserEndsCleanly();
        ProguardConfiguration config = parser.getConfigRawForTesting();
        assertEquals("PG", config.getRenameSourceFileAttribute());
        assertTrue(config.getKeepAttributes().sourceFile);
        assertFalse(config.getKeepAttributes().sourceDir);
      }
    }
  }

  @Test
  public void testRenameSourceFileAttribute_qouted_empty() throws Exception {
    for (String lineSeparator : lineSeparators) {
      for (Character quote : quotes) {
        reset();
        Path proguardConfig = writeTextToTempFile(lineSeparator,
            ImmutableList.of(
                "-renamesourcefileattribute " + quote + quote,
                "-keepattributes SourceFile"));
        ProguardConfigurationParser parser =
            new ProguardConfigurationParser(new DexItemFactory(), reporter);
        parser.parse(proguardConfig);
        verifyParserEndsCleanly();
        ProguardConfiguration config = parser.getConfigRawForTesting();
        assertEquals("", config.getRenameSourceFileAttribute());
        assertTrue(config.getKeepAttributes().sourceFile);
        assertFalse(config.getKeepAttributes().sourceDir);
      }
    }
  }

  private void testKeepattributes(List<String> expected, String config) {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(createConfigurationForTesting(ImmutableList.of(config)));
    verifyParserEndsCleanly();
    assertEquals(
        ProguardKeepAttributes.fromPatterns(expected),
        parser.getConfigRawForTesting().getKeepAttributes());
  }

  @Test
  public void parseKeepattributes() {
    List<String> xxxYYY = ImmutableList.of("xxx", "yyy");
    testKeepattributes(xxxYYY, "-keepattributes xxx,yyy");
    testKeepattributes(xxxYYY, "-keepattributes xxx, yyy");
    testKeepattributes(xxxYYY, "-keepattributes xxx ,yyy");
    testKeepattributes(xxxYYY, "-keepattributes xxx   ,   yyy");
    testKeepattributes(xxxYYY, "-keepattributes       xxx   ,   yyy     ");
    testKeepattributes(xxxYYY, "-keepattributes       xxx   ,   yyy     \n");
    String config =
        "-keepattributes Exceptions,InnerClasses,Signature,Deprecated,\n"
            + "          SourceFile,LineNumberTable,*Annotation*,EnclosingMethod\n";
    List<String> expected = ImmutableList.of(
        "Exceptions", "InnerClasses", "Signature", "Deprecated",
        "SourceFile", "LineNumberTable", "*Annotation*", "EnclosingMethod");
    testKeepattributes(expected, config);
  }

  private void testKeeppackagenames(ProguardPackageNameList expected, String config) {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(createConfigurationForTesting(ImmutableList.of(config)));
    verifyParserEndsCleanly();
    assertEquals(expected, parser.getConfigRawForTesting().getKeepPackageNamesPatterns());
  }

  @Test
  public void parseKeeppackagenames() {
    ProguardPackageNameList xxxYYY =
        ProguardPackageNameList.builder()
            .addPackageName(false, new ProguardPackageMatcher("xxx"))
            .addPackageName(false, new ProguardPackageMatcher("yyy"))
            .build();
    testKeeppackagenames(xxxYYY, "-keeppackagenames xxx,yyy");
    testKeeppackagenames(xxxYYY, "-keeppackagenames xxx, yyy");
    testKeeppackagenames(xxxYYY, "-keeppackagenames xxx ,yyy");
    testKeeppackagenames(xxxYYY, "-keeppackagenames xxx   ,   yyy");
    testKeeppackagenames(xxxYYY, "-keeppackagenames       xxx   ,   yyy     ");
    testKeeppackagenames(xxxYYY, "-keeppackagenames       xxx   ,   yyy     \n");
    testKeeppackagenames(xxxYYY, "-keeppackagenames \"xxx\",\"yyy\"");

    testKeeppackagenames(
        ProguardPackageNameList.builder()
            .addPackageName(false, new ProguardPackageMatcher("com.**"))
            .addPackageName(false, new ProguardPackageMatcher("org.*"))
            .build(),
        "-keeppackagenames com.**, org.*");

    testKeeppackagenames(
        ProguardPackageNameList.builder()
            .addPackageName(false, new ProguardPackageMatcher("c?m.**"))
            .addPackageName(false, new ProguardPackageMatcher("?r?.*"))
            .build(),
        "-keeppackagenames c?m.**, ?r?.*");

    testKeeppackagenames(
        ProguardPackageNameList.builder()
            .addPackageName(true, new ProguardPackageMatcher("c?m.**"))
            .addPackageName(true, new ProguardPackageMatcher("?r?.*"))
            .build(),
        "-keeppackagenames !c?m.**, !?r?.*");
  }

  @Test
  public void parseInvalidKeepattributes_brokenList() {
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(createConfigurationForTesting(ImmutableList.of("-keepattributes xxx,")));
      fail();
    } catch (AbortException e) {
      assertTrue(
          handler.errors.get(0).getDiagnosticMessage().contains("Expected list element at "));
    }
  }

  @Test
  public void parseInvalidKeepattributes_className() throws Exception {
    List<String> classNames = ImmutableList.of("androidx.annotation.Keep", "**.Keep", "K*<1>p");
    Path proguardConfig;
    for (String className : classNames) {
      reset();
      proguardConfig = writeTextToTempFile("-keepattributes " + className + ",*Annotations*");
      try {
        parser.parse(proguardConfig);
        fail("Expect to fail due to unsupported attribute.");
      } catch (AbortException e) {
        checkDiagnostics(
            handler.errors,
            proguardConfig,
            1,
            className.contains(".") ? className.indexOf('.') + 17 : className.length() + 13,
            "Unexpected attribute");
      }
      reset();
      proguardConfig = writeTextToTempFile("-keepattributes *Annotations*," + className);
      try {
        parser.parse(proguardConfig);
        fail("Expect to fail due to unsupported attribute.");
      } catch (AbortException e) {
        checkDiagnostics(
            handler.errors,
            proguardConfig,
            1,
            className.contains(".") ? className.indexOf('.') + 31 : className.length() + 27,
            "Unexpected attribute");
      }
    }
  }

  @Test
  public void parseUseUniqueClassMemberNames() throws IOException {
    Path proguardConfig = writeTextToTempFile("-useuniqueclassmembernames");
    new ProguardConfigurationParser(new DexItemFactory(), reporter).parse(proguardConfig);
    checkDiagnostics(
        handler.warnings, proguardConfig, 1, 1, "Ignoring", "-useuniqueclassmembernames");
  }

  @Test
  public void parseKeepParameterNames() throws Exception {
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(createConfigurationForTesting(ImmutableList.of(
          "-keepparameternames"
      )));
      parser.getConfig();
      fail();
    } catch (AbortException e) {
      assertTrue(handler.errors.get(0).getDiagnosticMessage().contains(
          "-keepparameternames is not supported"));
    }
  }

  @Test
  public void parseKeepParameterNamesWithoutMinification() throws Exception {
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(createConfigurationForTesting(ImmutableList.of(
        "-keepparameternames",
        "-dontobfuscate"
    )));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(config.isKeepParameterNames());

    parser = new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(createConfigurationForTesting(ImmutableList.of(
        "-keepparameternames"
    )));
    verifyParserEndsCleanly();
    parser.parse(createConfigurationForTesting(ImmutableList.of(
        "-dontobfuscate"
    )));
    verifyParserEndsCleanly();
    config = parser.getConfig();
    assertTrue(config.isKeepParameterNames());
  }

  @Test
  public void parseShortLine() throws IOException {
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(createConfigurationForTesting(Collections.singletonList("-")));
      fail();
    } catch (AbortException e) {
      assertEquals(1, handler.errors.size());
      assertTrue(handler.errors.get(0).getDiagnosticMessage().contains("-"));
    }
  }

  @Test
  public void parseNoLocals() throws IOException {
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(createConfigurationForTesting(Collections.singletonList("--no-locals")));
      fail();
    } catch (AbortException e) {

      assertEquals(1, handler.errors.size());
      assertTrue(handler.errors.get(0).getDiagnosticMessage().contains("--no-locals"));
    }
  }

  private void checkFileFilterMatchAnything(ProguardPathFilter filter) {
    assertTrue(filter.matches("x"));
    assertTrue(filter.matches("x/y"));
    assertTrue(filter.matches("x/y/x"));
  }

  @Test
  public void parse_adaptresourcexxx_keepdirectories_noArguments1() {
    ProguardConfiguration config = parseAndVerifyParserEndsCleanly(ImmutableList.of(
        "-adaptresourcefilenames",
        "-adaptresourcefilecontents",
        "-keepdirectories"
    ));
    checkFileFilterMatchAnything(config.getAdaptResourceFilenames());
    checkFileFilterMatchAnything(config.getAdaptResourceFileContents());
    checkFileFilterMatchAnything(config.getKeepDirectories());
  }

  @Test
  public void parse_adaptresourcexxx_keepdirectories_noArguments2() {
    ProguardConfiguration config = parseAndVerifyParserEndsCleanly(ImmutableList.of(
        "-keepdirectories",
        "-adaptresourcefilenames",
        "-adaptresourcefilecontents"
    ));
    checkFileFilterMatchAnything(config.getAdaptResourceFilenames());
    checkFileFilterMatchAnything(config.getAdaptResourceFileContents());
    checkFileFilterMatchAnything(config.getKeepDirectories());
  }

  @Test
  public void parse_adaptresourcexxx_keepdirectories_noArguments3() {
    ProguardConfiguration config = parseAndVerifyParserEndsCleanly(ImmutableList.of(
        "-adaptresourcefilecontents",
        "-keepdirectories",
        "-adaptresourcefilenames"
    ));
    checkFileFilterMatchAnything(config.getAdaptResourceFilenames());
    checkFileFilterMatchAnything(config.getAdaptResourceFileContents());
    checkFileFilterMatchAnything(config.getKeepDirectories());
  }

  private String FILE_FILTER_SINGLE = "xxx/*";

  private void checkFileFilterSingle(ProguardPathFilter filter) {
    assertTrue(filter.matches("xxx/x"));
    assertTrue(filter.matches("xxx/"));
    assertFalse(filter.matches("xxx/yyy/z"));
    assertFalse(filter.matches("xxx"));
  }

  @Test
  public void parse_adaptresourcexxx_keepdirectories_singleArgument() {
    ProguardConfiguration config = parseAndVerifyParserEndsCleanly(ImmutableList.of(
        "-adaptresourcefilenames " + FILE_FILTER_SINGLE,
        "-adaptresourcefilecontents " + FILE_FILTER_SINGLE,
        "-keepdirectories " + FILE_FILTER_SINGLE
    ));
    checkFileFilterSingle(config.getAdaptResourceFilenames());
    checkFileFilterSingle(config.getAdaptResourceFileContents());
    checkFileFilterSingle(config.getKeepDirectories());
  }

  private String FILE_FILTER_MULTIPLE =
      "xxx/*, !**.gif  ,images/**  ,  com/myapp/**/*.xml,com/mylib/*/*.xml";

  private void checkFileFilterMultiple(ProguardPathFilter filter) {
    assertTrue(filter.matches("xxx/x"));
    assertTrue(filter.matches("xxx/x.gif"));
    assertTrue(filter.matches("images/x.jpg"));
    assertTrue(filter.matches("images/xxx/x.jpg"));
    assertTrue(filter.matches("com/myapp/package1/x.xml"));
    assertTrue(filter.matches("com/myapp/package1/package2/x.xml"));
    assertTrue(filter.matches("com/mylib/package1/x.xml"));
    assertFalse(filter.matches("x.gif"));
    assertFalse(filter.matches("images/x.gif"));
    assertFalse(filter.matches("images/xxx/y.gif"));
    assertFalse(filter.matches("images/xxx/yyy/z.gif"));
    assertFalse(filter.matches("com/myapp/package1/x.jpg"));
    assertFalse(filter.matches("com/myapp/package1/package2/x.jpg"));
    assertFalse(filter.matches("com/mylib/package1/package2/x.xml"));
  }

  @Test
  public void parse_adaptresourcexxx_keepdirectories_multipleArgument() {
    ProguardConfiguration config = parseAndVerifyParserEndsCleanly(ImmutableList.of(
        "-adaptresourcefilenames " + FILE_FILTER_MULTIPLE,
        "-adaptresourcefilecontents " + FILE_FILTER_MULTIPLE,
        "-keepdirectories " + FILE_FILTER_MULTIPLE
    ));
    checkFileFilterMultiple(config.getAdaptResourceFilenames());
    checkFileFilterMultiple(config.getAdaptResourceFileContents());
    checkFileFilterMultiple(config.getKeepDirectories());
  }

  @Test
  public void parse_adaptresourcexxx_keepdirectories_leadingComma() {
    List<String> options = ImmutableList.of(
        "-adaptresourcefilenames", "-adaptresourcefilecontents", "-keepdirectories");
    for (String option : options) {
      try {
        reset();
        parser.parse(createConfigurationForTesting(ImmutableList.of(option + " ,")));
        fail("Expect to fail due to the lack of path filter.");
      } catch (AbortException e) {
        checkDiagnostics(handler.errors, null, 1, option.length() + 2, "Path filter expected");
      }
    }
  }

  @Test
  public void parse_adaptresourcexxx_keepdirectories_emptyListElement() {
    List<String> options = ImmutableList.of(
        "-adaptresourcefilenames", "-adaptresourcefilecontents", "-keepdirectories");
    for (String option : options) {
      try {
        reset();
        parser.parse(createConfigurationForTesting(ImmutableList.of(option + " xxx,,yyy")));
        fail("Expect to fail due to the lack of path filter.");
      } catch (AbortException e) {
        checkDiagnostics(handler.errors, null, 1, option.length() + 6, "Path filter expected");
      }
    }
  }

  @Test
  public void parse_adaptresourcexxx_keepdirectories_trailingComma() {
    List<String> options = ImmutableList.of(
        "-adaptresourcefilenames", "-adaptresourcefilecontents", "-keepdirectories");
    for (String option : options) {
      try {
        reset();
        parser.parse(createConfigurationForTesting(ImmutableList.of(option + " xxx,")));
        fail("Expect to fail due to the lack of path filter.");
      } catch (AbortException e) {
        checkDiagnostics(handler.errors, null, 1, option.length() + 6, "Path filter expected");
      }
    }
  }

  @Test
  public void parse_testInlineOptions() {
    List<String> options = ImmutableList.of(
        "-neverinline", "-forceinline");
    for (String option : options) {
      try {
        reset();
        parser.parse(createConfigurationForTesting(ImmutableList.of(option + " class A { *; }")));
        fail("Expect to fail due to testing option being turned off.");
      } catch (AbortException e) {
        assertEquals(1, handler.errors.size());
        checkDiagnostics(handler.errors, 0, null, 1, 1, "Unknown option \"" + option + "\"");
      }
    }
  }

  @Test
  public void parse_if() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if   class **$$ModuleAdapter",
        "-keep class A",
        "-if   class **$$InjectAdapter",
        "-keep class B",
        "-if   class **$$StaticInjection",
        "-keep class C",
        "-keepnames class dagger.Lazy"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    // Three -if rules and one independent -keepnames
    assertEquals(4, config.getRules().size());
    long ifCount =
        config.getRules().stream().filter(rule -> rule instanceof ProguardIfRule).count();
    assertEquals(3, ifCount);
    ProguardIfRule if0 = (ProguardIfRule) config.getRules().get(0);
    assertEquals("**$$ModuleAdapter", if0.getClassNames().toString());
    assertEquals(ProguardKeepRuleType.KEEP, if0.subsequentRule.getType());
    assertEquals("A", if0.subsequentRule.getClassNames().toString());
    ProguardIfRule if1 = (ProguardIfRule) config.getRules().get(1);
    assertEquals("**$$InjectAdapter", if1.getClassNames().toString());
    assertEquals(ProguardKeepRuleType.KEEP, if1.subsequentRule.getType());
    assertEquals("B", if1.subsequentRule.getClassNames().toString());
    ProguardIfRule if2 = (ProguardIfRule) config.getRules().get(2);
    assertEquals("**$$StaticInjection", if2.getClassNames().toString());
    assertEquals(ProguardKeepRuleType.KEEP, if2.subsequentRule.getType());
    assertEquals("C", if2.subsequentRule.getClassNames().toString());
  }

  @Test
  public void parse_if_nthWildcard() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **$R**",
        "-keep class **$D<2>"  // <2> corresponds to the 2nd ** in -if rule.
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertEquals(1, config.getRules().size());
    ProguardIfRule if0 = (ProguardIfRule) config.getRules().get(0);
    assertEquals("**$R**", if0.getClassNames().toString());
    assertEquals(ProguardKeepRuleType.KEEP, if0.subsequentRule.getType());
    assertEquals("**$D<2>", if0.subsequentRule.getClassNames().toString());

    // Test <2> literally refers to the second wildcard in the rule.
    Iterator<ProguardWildcard> it1 = if0.getClassNames().getWildcards().iterator();
    it1.next();
    ProguardWildcard secondWildcardInIf = it1.next();
    assertTrue(secondWildcardInIf.isPattern());
    Iterator<ProguardWildcard> it2 = if0.subsequentRule.getWildcards().iterator();
    it2.next();
    ProguardWildcard backReference = it2.next();
    assertTrue(backReference.isBackReference());
    assertSame(secondWildcardInIf.asPattern(), backReference.asBackReference().reference);

    verifyWithProguard6(proguardConfig);
  }

  @Test
  public void parse_if_nthWildcard_notNumber_literalN() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **$R**",
        "-keep class **D<n>"
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 2, 13,
          "Use of generics not allowed for java type");
    }
    verifyFailWithProguard6(proguardConfig, "Use of generics not allowed for java type");
  }

  @Test
  public void parse_if_nthWildcard_notNumber_asterisk_inClassName() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **$R**",
        "-keep class **D<*>"
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 2, 13,
          "Use of generics not allowed for java type");
    }
    verifyFailWithProguard6(proguardConfig, "Use of generics not allowed for java type");
  }

  @Test
  public void parse_if_nthWildcard_notNumber_asterisk_inMemberName() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **$R**",
        "-keep class **D<2> {",
        "  int id<*>;",
        "}"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();

    verifyWithProguard6(proguardConfig);
  }

  @Test
  public void parse_if_nestedAngularBrackets_inMemberName() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **$R**",
        "-keep class **D<2> {",
        "  int id<<*>>;",
        "}"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    checkDiagnostics(handler.warnings, proguardConfig, 3, 7, "The field name \"id<<*>>\" is");

    verifyWithProguard6(proguardConfig);
  }

  @Test
  public void parse_if_nestedAngularBrackets_outOfRange() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **$R**",
        "-keep class **D<2> {",
        "  int id<<4>>;",  // There are 3 previous referable wildcards in this rule.
        "}"
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 4, 2,
          "Wildcard", "<4>", "invalid");
    }
    verifyFailWithProguard6(proguardConfig, "Invalid reference to wildcard (4,");
  }

  @Test
  public void parse_if_nthWildcard_outOfRange_tooSmall() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **$R**",
        "-keep class **D<0>"  // nth wildcard starts from 1, not 0.
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 2, 13,
          "Wildcard", "<0>", "invalid");
    }
    verifyFailWithProguard6(proguardConfig, "Invalid reference to wildcard (0,");
  }

  @Test
  public void parse_if_nthWildcard_outOfRange_tooBig() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **$R**",
        "-keep class **D<4>"  // There are 3 previous wildcards in this rule.
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 3, 1,
          "Wildcard", "<4>", "invalid");
    }
    verifyFailWithProguard6(proguardConfig, "Invalid reference to wildcard (4,");
  }

  @Test
  public void parse_if_nthWildcard_outOfRange_inIf() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **$R<2>", // There is only one wildcard prior to <2>.
        "-keep class **D<2>"
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 3, 1,
          "Wildcard", "<2>", "invalid");
    }
    verifyFailWithProguard6(proguardConfig, "Invalid reference to wildcard (2,");
  }

  @Test
  public void parse_if_nthWildcard_not_referable() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **.R {",
        "  int id?;",
        "}",
        "-keep class <1>.D<2> {",
        "  int id<3>;",  // Only ** and ? are referable wildcards.
        "}"
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 6, 2,
          "Wildcard", "<3>", "invalid");
    }
    verifyFailWithProguard6(proguardConfig, "Invalid reference to wildcard (3,");
  }

  @Test
  public void parse_if_nthWildcard_not_referable_after_backreference() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if class **.*User {",
        "  @<1>.*<2> <methods>;", // As back reference starts, * in the middle is not referable.
        "}",
        "-keep @interface <1>.<3><2>"
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 5, 1,
          "Wildcard", "<3>", "invalid");
    }
    verifyFailWithProguard6(proguardConfig, "Invalid reference to wildcard (3,");
  }

  @Test
  public void parse_if_if() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if   class **$$ModuleAdapter",
        "-if   class **$$InjectAdapter"
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 1, 1,
          "Expecting", "'-keep'", "after", "'-if'");
    }
    verifyFailWithProguard6(proguardConfig, "Expecting '-keep' option after '-if' option");
  }

  @Test
  public void parse_if_end() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-if   class **$$ModuleAdapter"
    );
    try {
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(proguardConfig);
      fail();
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, proguardConfig, 1, 1,
          "Expecting", "'-keep'", "after", "'-if'");
    }
    verifyFailWithProguard6(proguardConfig, "Expecting '-keep' option after '-if' option");
  }

  @Test
  public void parse_assumenoexternalsideeffects() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-assumenoexternalsideeffects class java.lang.StringBuilder {",
        "  public java.lang.StringBuilder();",
        "  public java.lang.StringBuilder(int);",
        "  public java.lang.StringBuilder(java.lang.String);",
        "  public java.lang.StringBuilder append(java.lang.Object);",
        "  public java.lang.StringBuilder append(java.lang.String);",
        "  public java.lang.StringBuilder append(java.lang.StringBuffer);",
        "  public java.lang.StringBuilder append(char[]);",
        "  public java.lang.StringBuilder append(char[], int, int);",
        "  public java.lang.StringBuilder append(boolean);",
        "  public java.lang.StringBuilder append(char);",
        "  public java.lang.StringBuilder append(int);",
        "  public java.lang.StringBuilder append(long);",
        "  public java.lang.StringBuilder append(float);",
        "  public java.lang.StringBuilder append(double);",
        "  public java.lang.String toString();",
        "}"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    checkDiagnostics(handler.warnings, proguardConfig, 1, 1,
        "Ignoring", "-assumenoexternalsideeffects");
  }

  @Test
  public void parse_assumenoescapingparameters() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-assumenoescapingparameters class java.lang.System {",
        "  public static void arraycopy(java.lang.Object, int, java.lang.Object, int, int);",
        "}"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    checkDiagnostics(handler.warnings, proguardConfig, 1, 1,
        "Ignoring", "-assumenoescapingparameters");
  }

  @Test
  public void parse_assumenoexternalreturnvalues() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-assumenoexternalreturnvalues class java.lang.StringBuilder {",
        "  public java.lang.StringBuilder append(java.lang.Object);",
        "  public java.lang.StringBuilder append(java.lang.String);",
        "  public java.lang.StringBuilder append(java.lang.StringBuffer);",
        "  public java.lang.StringBuilder append(char[]);",
        "  public java.lang.StringBuilder append(char[], int, int);",
        "  public java.lang.StringBuilder append(boolean);",
        "  public java.lang.StringBuilder append(char);",
        "  public java.lang.StringBuilder append(int);",
        "  public java.lang.StringBuilder append(long);",
        "  public java.lang.StringBuilder append(float);",
        "  public java.lang.StringBuilder append(double);",
        "}"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    checkDiagnostics(handler.warnings, proguardConfig, 1, 1,
        "Ignoring", "-assumenoexternalreturnvalues");
  }

  @Test
  public void parse_dump_withoutFile() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-dump"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    checkDiagnostics(handler.warnings, proguardConfig, 1, 1,
        "Ignoring", "-dump");
  }

  @Test
  public void parse_dump_withFile() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-dump class_files.txt"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    checkDiagnostics(handler.warnings, proguardConfig, 1, 1,
        "Ignoring", "-dump");
  }

  @Test
  public void parse_android() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-android"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();
  }

  @Test
  public void parse_mergeinterfaceaggressively() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-mergeinterfacesaggressively"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();
  }

  @Test
  public void parse_addconfigurationdebugging() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-addconfigurationdebugging"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();
    assertTrue(parser.getConfig().isConfigurationDebugging());
  }

  @Test
  public void parse_regress74508478() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-keep class A {",
        "  A <fields>;",
        "}"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    checkDiagnostics(handler.warnings, proguardConfig, 2, 5, "The field name \"<fields>\" is");
    verifyWithProguard(proguardConfig);
  }

  @Test
  public void parse_regress79925760() throws Exception {
    Path proguardConfig = writeTextToTempFile(
        "-keep public @ interface test.MyAnnotation"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();

    ProguardConfiguration config = parser.getConfig();
    assertEquals(1, config.getRules().size());
    ProguardKeepRule rule = (ProguardKeepRule) config.getRules().get(0);
    assertEquals(ProguardClassType.ANNOTATION_INTERFACE, rule.getClassType());

    verifyWithProguard(proguardConfig);
  }

  @Test
  public void parse_regress110021323() throws Exception {
    Path proguardConfig = writeTextToTempFile(
      "-keepclassmembernames class A {",
      "  <public methods>;",
      "  <public fields>;",
      "}"
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    assertEquals(4, handler.warnings.size());
    checkDiagnostics(handler.warnings, 0, proguardConfig, 2, 3, "The type \"<public\" is");
    checkDiagnostics(handler.warnings, 1, proguardConfig, 2, 11, "The field name \"methods>\" is");
    checkDiagnostics(handler.warnings, 2, proguardConfig, 3, 3, "The type \"<public\" is");
    checkDiagnostics(handler.warnings, 3, proguardConfig, 3, 11, "The field name \"fields>\" is");

    verifyWithProguard(proguardConfig);
  }

  private void checkRulesSourceSnippet(List<String> sourceRules) {
    checkRulesSourceSnippet(sourceRules, sourceRules, false);
  }

  private void checkRulesSourceSnippet(
      List<String> sourceRules, List<String> expected, boolean trim) {
    reset();
    parser.parse(createConfigurationForTesting(sourceRules));
    verifyParserEndsCleanly();
    List<ProguardConfigurationRule> rules = parser.getConfig().getRules();
    assertEquals(expected.size(), rules.size());
    for (int i = 0; i < expected.size(); i++) {
      assertEquals(trim ? expected.get(i).trim() : expected.get(i), rules.get(i).getSource());
    }
  }

  @Test
  public void accurateSourceSnippet() {
    String rule1 = String.join(System.lineSeparator(), ImmutableList.of("-keep class A  {  *;  }"));
    String rule2 =
        String.join(System.lineSeparator(), ImmutableList.of("-keep class A  ", "{  *;  ", "}"));
    String rule3 =
        String.join(
            System.lineSeparator(), ImmutableList.of("-checkdiscard class A  ", "{  *;  ", "}"));

    checkRulesSourceSnippet(ImmutableList.of(rule1));
    checkRulesSourceSnippet(ImmutableList.of(rule2));
    checkRulesSourceSnippet(ImmutableList.of(rule3));
    checkRulesSourceSnippet(ImmutableList.of(rule1, rule2, rule3));
  }

  @Test
  public void accurateSourceSnippet_withWhitespace() {
    Iterable<String> nonEmptyWhiteSpace =
        whiteSpace.stream().filter(space -> !space.equals("")).collect(Collectors.toList());
    for (String space : nonEmptyWhiteSpace) {
      String rule1 =
          String.join(System.lineSeparator(), ImmutableList.of("  -keep class A  {  *;  }  "))
              .replaceAll(" {2}", space);
      String rule2 =
          String.join(
                  System.lineSeparator(), ImmutableList.of("-keep class A  ", "{  *;  ", "}", ""))
              .replaceAll(" {2}", space);

      checkRulesSourceSnippet(ImmutableList.of(rule1), ImmutableList.of(rule1), true);
      checkRulesSourceSnippet(
          ImmutableList.of("#Test comment ", "", rule1), ImmutableList.of(rule1), true);
      checkRulesSourceSnippet(
          ImmutableList.of("#Test comment ", "", rule1, "", "#Test comment ", ""),
          ImmutableList.of(rule1),
          true);
      checkRulesSourceSnippet(ImmutableList.of(rule2), ImmutableList.of(rule2), true);
      checkRulesSourceSnippet(ImmutableList.of(rule1, rule2), ImmutableList.of(rule1, rule2), true);
      checkRulesSourceSnippet(
          ImmutableList.of(
              "#Test comment ", "", rule1, " ", "#Test comment ", "", rule2, "#Test comment ", ""),
          ImmutableList.of(rule1, rule2),
          true);
    }
  }

  @Test
  public void parseOptionalArgumentsFollowedByArobaseInclude() throws Exception {
    Path includeFile = writeTextToTempFile(
        "-renamesourcefileattribute SRC"
    );
    Path proguardConfig = writeTextToTempFile(
        "-printconfiguration",
        "@" + includeFile.toAbsolutePath()
    );
    ProguardConfigurationParser parser =
        new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(proguardConfig);
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    assertTrue(config.isPrintConfiguration());
    assertNull(config.getPrintConfigurationFile());
    assertEquals("SRC", config.getRenameSourceFileAttribute());
  }

  private void testFlagWithFilenames(
      String flag,
      List<String> values,
      Function<ProguardConfiguration, Path> extractPath,
      BiConsumer<String, String> check) {
    for (String value : values) {
      reset();
      parser.parse(createConfigurationForTesting(ImmutableList.of(flag + " " + value)));
      verifyParserEndsCleanly();
      ProguardConfiguration config = parser.getConfig();
      check.accept(value, extractPath.apply(config).toString());
    }
  }

  @Test
  public void parseSingleFileNameOptions() {
    List<String> fileNames = ImmutableList.of(
        "xxx",
        "xxx" + File.pathSeparatorChar + "xxx");
    testFlagWithFilenames("-printusage", fileNames,
        ProguardConfiguration::getPrintUsageFile, Assert::assertEquals);
    testFlagWithFilenames("-printconfiguration", fileNames,
        ProguardConfiguration::getPrintConfigurationFile, Assert::assertEquals);
    testFlagWithFilenames("-printmapping", fileNames,
        ProguardConfiguration::getPrintMappingFile, Assert::assertEquals);
    testFlagWithFilenames("-applymapping", fileNames,
        ProguardConfiguration::getApplyMappingFile, Assert::assertEquals);
    // The parsed value of -basedirectory is not available in the configuration.
    testFlagWithFilenames("-basedirectory", fileNames, (x) -> Paths.get(""), (x, y) -> {});
    testFlagWithFilenames("-printseeds", fileNames,
        ProguardConfiguration::getSeedFile, Assert::assertEquals);
    // TODO(sgjesse): Add tests for -obfuscationdictionary, -classobfuscationdictionary,
    // -packageobfuscationdictionary and -include
  }

  private void checkQuotedFileName(String quoted, String parsed) {
    assertTrue(quoted.charAt(0) == '\'' || quoted.charAt(0) == '\"');
    assertTrue(quoted.charAt(0) == quoted.charAt(quoted.length() - 1));
    assertEquals(quoted.substring(1, quoted.length() - 1), parsed);
  }

  @Test
  public void parseSingleFleNameOptionsQuoted() {
    List<String> fileNames = new ArrayList<>();
    fileNames.add("'xxx'");
    fileNames.add("\"xxx\"");
    fileNames.add("'xxx xxx\'");
    fileNames.add("\"xxx xxx\"");
    fileNames.add("\"'xxx'\"");
    fileNames.add("\" xxx xxx (\"");
    fileNames.add("' xxx xxx ('");
    // Java Path implementation on Windows does not allow " or trailing
    // spaces in file names.
    if (!ToolHelper.isWindows()) {
      fileNames.add("'\"xxx\"'");
      fileNames.add("\" xxx xxx \"");
      fileNames.add("' xxx xxx '");
    }
    testFlagWithFilenames("-printusage", fileNames,
        ProguardConfiguration::getPrintUsageFile, this::checkQuotedFileName);
    testFlagWithFilenames("-printconfiguration", fileNames,
        ProguardConfiguration::getPrintConfigurationFile, this::checkQuotedFileName);
    testFlagWithFilenames("-printmapping", fileNames,
        ProguardConfiguration::getPrintMappingFile, this::checkQuotedFileName);
    testFlagWithFilenames("-applymapping", fileNames,
        ProguardConfiguration::getApplyMappingFile, this::checkQuotedFileName);
    // The parsed value of -basedirectory is not available in the configuration.
    testFlagWithFilenames("-basedirectory", fileNames, (x) -> Paths.get(""), (x, y) -> {});
    testFlagWithFilenames("-printseeds", fileNames,
        ProguardConfiguration::getSeedFile, this::checkQuotedFileName);
    // TODO(sgjesse): Add tests for -obfuscationdictionary, -classobfuscationdictionary,
    // -packageobfuscationdictionary and -include
  }

  private void testFlagWithFilenamesWithSystemProperty(
      String flag,
      List<String> values,
      Function<ProguardConfiguration, Path> extractPath,
      BiConsumer<String, String> check) {
    for (String value : values) {
      reset();
      parser.parse(createConfigurationForTesting(ImmutableList.of(flag + " " + value)));
      verifyParserEndsCleanly();
      ProguardConfiguration config = parser.getConfig();
      Path path = extractPath.apply(config);
      check.accept(
          value
              .replaceAll("<java.home>", Matcher.quoteReplacement(System.getProperty("java.home")))
              .replaceAll("<user.home>", Matcher.quoteReplacement(System.getProperty("user.home"))),
          path.toString());
    }
  }

  @Test
  public void parseFlagWithFilenamesWithSystemProperty() {
    List<String> fileNames = new ArrayList<>();
    fileNames.add("<java.home>");
    fileNames.add("<user.home>");
    if (!ToolHelper.isWindows()) {
      // If the system property has e.g. C:\ prefix, then these file names
      // will not work on Windows.
      fileNames.add("xxx<java.home>");
      fileNames.add("xxx<user.home>");
    }
    fileNames.add("<java.home>" +  File.separatorChar + "xxx");
    fileNames.add("<user.home>" +  File.separatorChar + "xxx");
    if (!ToolHelper.isWindows()) {
      fileNames.add("xxx<java.home>/xxx");
      fileNames.add("xxx<user.home>/xxx");
      fileNames.add("<java.home><java.home>");
      fileNames.add("<user.home><user.home>");
      fileNames.add("<java.home><user.home>");
      fileNames.add("<user.home><java.home>");
      // The characters < and > are not allowed in paths on Windows.
      fileNames.add(">");
      fileNames.add("<");
      fileNames.add("<<<<");
      fileNames.add("><");
      fileNames.add(">><<");
    }
    testFlagWithFilenamesWithSystemProperty("-printusage", fileNames,
        ProguardConfiguration::getPrintUsageFile, Assert::assertEquals);
    testFlagWithFilenamesWithSystemProperty("-printconfiguration", fileNames,
        ProguardConfiguration::getPrintConfigurationFile, Assert::assertEquals);
    testFlagWithFilenamesWithSystemProperty("-printmapping", fileNames,
        ProguardConfiguration::getPrintMappingFile, Assert::assertEquals);
    testFlagWithFilenamesWithSystemProperty("-applymapping", fileNames,
        ProguardConfiguration::getApplyMappingFile, Assert::assertEquals);
    // The parsed value of -basedirectory is not available in the configuration.
    testFlagWithFilenamesWithSystemProperty("-basedirectory", fileNames,
        (x) -> Paths.get(""), (x, y) -> {});
    testFlagWithFilenamesWithSystemProperty("-printseeds", fileNames,
        ProguardConfiguration::getSeedFile, Assert::assertEquals);
    // TODO(sgjesse): Add tests for -obfuscationdictionary, -classobfuscationdictionary,
    // -packageobfuscationdictionary and -include
  }

  @Test
  public void pasteFlagWithFilenamesWithSystemProperty_empty() {
    try {
      parser.parse(createConfigurationForTesting(ImmutableList.of("-printusage <>")));
      fail("Expect to fail due to the lack of file name.");
    } catch (AbortException e) {
      checkDiagnostics(handler.errors, null, 1, 15, "Value of system property '' not found");
    }
  }

  @Test
  public void pasteFlagWithFilenamesWithSystemProperty_notFound() {
    // Find a non-existent system property.
    String property = "x";
    while (System.getProperty(property) != null) {
      property = property + "x";
    }

    try {
      parser.parse(
          createConfigurationForTesting(ImmutableList.of("-printusage <" + property + ">")));
      fail("Expect to fail due to the lack of file name.");
    } catch (AbortException e) {
      checkDiagnostics(
          handler.errors, null, 1, 16, "Value of system property '" + property + "' not found");
    }
  }

  private void testFlagWithQuotedValue(
      String flag, String value, BiConsumer<PackageObfuscationMode, String> checker) {
    reset();
    parser.parse(createConfigurationForTesting(ImmutableList.of(flag + " " + value)));
    verifyParserEndsCleanly();
    ProguardConfiguration config = parser.getConfig();
    checker.accept(config.getPackageObfuscationMode(), config.getPackagePrefix());
  }

  private void testFlagWithQuotedValueFailure(
      String flag, String value, Supplier<Void> checker) {
    try {
      reset();
      parser.parse(createConfigurationForTesting(ImmutableList.of(flag + " " + value)));
      fail("Expect to fail due to un-closed quote.");
    } catch (AbortException e) {
      checker.get();
    }
  }

  @Test
  public void parseRepackageclassesQuotes() {
    testFlagWithQuotedValue("-repackageclasses", "'xxx'", (mode, prefix) -> {
      assertEquals(PackageObfuscationMode.REPACKAGE, mode);
      assertEquals("xxx", prefix);
    });
    testFlagWithQuotedValue("-repackageclasses", "\"xxx\"", (mode, prefix) -> {
      assertEquals(PackageObfuscationMode.REPACKAGE, mode);
      assertEquals("xxx", prefix);
    });
    testFlagWithQuotedValueFailure("-repackageclasses", "'xxx", () -> {
      checkDiagnostics(handler.errors, null, 1, 23, "Missing closing quote");
      return null;
    });
    testFlagWithQuotedValueFailure("-repackageclasses", "'xxx\"", () -> {
      checkDiagnostics(handler.errors, null, 1, 23, "Missing closing quote");
      return null;
    });
    testFlagWithQuotedValueFailure("-repackageclasses", "\"xxx", () -> {
      checkDiagnostics(handler.errors, null, 1, 23, "Missing closing quote");
      return null;
    });
    testFlagWithQuotedValueFailure("-repackageclasses", "\"xxx'", () -> {
      checkDiagnostics(handler.errors, null, 1, 23, "Missing closing quote");
      return null;
    });
  }

  @Test
  public void parseFlattenpackagehierarchyQuotes() {
    testFlagWithQuotedValue("-flattenpackagehierarchy", "'xxx'", (mode, prefix) -> {
      assertEquals(PackageObfuscationMode.FLATTEN, mode);
      assertEquals("xxx", prefix);
    });
    testFlagWithQuotedValue("-flattenpackagehierarchy", "\"xxx\"", (mode, prefix) -> {
      assertEquals(PackageObfuscationMode.FLATTEN, mode);
      assertEquals("xxx", prefix);
    });
    testFlagWithQuotedValueFailure("-flattenpackagehierarchy", "'xxx", () -> {
      checkDiagnostics(handler.errors, null, 1, 30, "Missing closing quote");
      return null;
    });
    testFlagWithQuotedValueFailure("-flattenpackagehierarchy", "'xxx\"", () -> {
      checkDiagnostics(handler.errors, null, 1, 30, "Missing closing quote");
      return null;
    });
    testFlagWithQuotedValueFailure("-flattenpackagehierarchy", "\"xxx", () -> {
      checkDiagnostics(handler.errors, null, 1, 30, "Missing closing quote");
      return null;
    });
    testFlagWithQuotedValueFailure("-flattenpackagehierarchy", "\"xxx'", () -> {
      checkDiagnostics(handler.errors, null, 1, 30, "Missing closing quote");
      return null;
    });
  }

  private ProguardConfiguration parseAndVerifyParserEndsCleanly(List<String> config) {
    parser.parse(createConfigurationForTesting(config));
    verifyParserEndsCleanly();
    return parser.getConfig();
  }

  private void verifyParserEndsCleanly() {
    assertEquals(0, handler.infos.size());
    assertEquals(0, handler.warnings.size());
    assertEquals(0, handler.errors.size());
  }

  private void verifyWithProguard(Path proguardConfig) throws Exception {
    if (isRunProguard()) {
      // Add a keep rule for the test class as Proguard will fail if the resulting output jar is
      // empty
      Class classToKeepForTest = EmptyMainClassForProguardTests.class;
      Path additionalProguardConfig = writeTextToTempFile(
          "-keep class " + classToKeepForTest.getCanonicalName() + " {",
          "  public static void main(java.lang.String[]);",
          "}"
      );
      Path proguardedJar =
          File.createTempFile("proguarded", FileUtils.JAR_EXTENSION, temp.getRoot()).toPath();
      ProcessResult result = ToolHelper.runProguardRaw(
          jarTestClasses(ImmutableList.of(classToKeepForTest)),
          proguardedJar,
          ImmutableList.of(proguardConfig, additionalProguardConfig),
          null);
      assertEquals(0, result.exitCode);
      CodeInspector proguardInspector = new CodeInspector(readJar(proguardedJar));
      assertEquals(1, proguardInspector.allClasses().size());
    }
  }

  private void verifyWithProguard6(Path proguardConfig) throws Exception {
    if (isRunProguard()) {
      // Add a keep rule for the test class as Proguard will fail if the resulting output jar is
      // empty
      Class classToKeepForTest = EmptyMainClassForProguardTests.class;
      Path additionalProguardConfig = writeTextToTempFile(
          "-keep class " + classToKeepForTest.getCanonicalName() + " {",
          "  public static void main(java.lang.String[]);",
          "}"
      );
      Path proguardedJar =
          File.createTempFile("proguarded", FileUtils.JAR_EXTENSION, temp.getRoot()).toPath();
      ProcessResult result = ToolHelper.runProguard6Raw(
          jarTestClasses(ImmutableList.of(classToKeepForTest)),
          proguardedJar,
          ImmutableList.of(proguardConfig, additionalProguardConfig),
          null);
      assertEquals(0, result.exitCode);
      CodeInspector proguardInspector = new CodeInspector(readJar(proguardedJar));
      assertEquals(1, proguardInspector.allClasses().size());
    }
  }

  private void verifyFailWithProguard6(Path proguardConfig, String expectedMessage)
      throws Exception{
    if (isRunProguard()) {
      // No need for a keep rule for this class, as we are expecting Proguard to fail with the
      // specified message.
      Class classForTest = EmptyMainClassForProguardTests.class;
      Path proguardedJar =
          File.createTempFile("proguarded", FileUtils.JAR_EXTENSION, temp.getRoot()).toPath();
      ProcessResult result = ToolHelper.runProguard6Raw(
          jarTestClasses(ImmutableList.of(classForTest)), proguardedJar, proguardConfig, null);
      assertNotEquals(0, result.exitCode);
      assertThat(result.stderr, containsString(expectedMessage));
    }
  }

  @Test
  public void b124181032() {
    // Test spaces and quotes in class name list.
    ProguardConfigurationParser parser;
    parser = new ProguardConfigurationParser(new DexItemFactory(), reporter);
    parser.parse(
        createConfigurationForTesting(
            ImmutableList.of(
                "-keepclassmembers class \"a.b.c.**\" ,"
                    + " !**d , '!**e' , \"!**f\" , g , 'h' , \"i\" { ",
                "<fields>;",
                "<init>();",
                "}")));
    List<ProguardConfigurationRule> rules = parser.getConfig().getRules();
    assertEquals(1, rules.size());
    ProguardConfigurationRule rule = rules.get(0);
    assertEquals(ProguardKeepRuleType.KEEP_CLASS_MEMBERS.toString(), rule.typeString());
    assertEquals("a.b.c.**,!**d,!**e,!**f,g,h,i", rule.getClassNames().toString());
  }

  @Test
  public void directiveAfterRepackagingRuleTest() {
    List<PackageObfuscationMode> packageObfuscationModes =
        ImmutableList.of(PackageObfuscationMode.FLATTEN, PackageObfuscationMode.REPACKAGE);
    for (PackageObfuscationMode packageObfuscationMode : packageObfuscationModes) {
      String directive =
          packageObfuscationMode == PackageObfuscationMode.FLATTEN
              ? "-flattenpackagehierarchy"
              : "-repackageclasses";
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(createConfigurationForTesting(ImmutableList.of(directive + " -keep class *")));
      ProguardConfiguration configuration = parser.getConfig();
      assertEquals(packageObfuscationMode, configuration.getPackageObfuscationMode());
      assertEquals("", configuration.getPackagePrefix());

      List<ProguardConfigurationRule> rules = configuration.getRules();
      assertEquals(1, rules.size());

      ProguardConfigurationRule rule = rules.get(0);
      assertEquals(ProguardKeepRuleType.KEEP.toString(), rule.typeString());
      assertEquals("*", rule.getClassNames().toString());
    }
  }

  @Test
  public void arobaseAfterRepackagingRuleTest() throws IOException {
    Path includeFile = writeTextToTempFile("-keep class *");
    List<PackageObfuscationMode> packageObfuscationModes =
        ImmutableList.of(PackageObfuscationMode.FLATTEN, PackageObfuscationMode.REPACKAGE);
    for (PackageObfuscationMode packageObfuscationMode : packageObfuscationModes) {
      String directive =
          packageObfuscationMode == PackageObfuscationMode.FLATTEN
              ? "-flattenpackagehierarchy"
              : "-repackageclasses";
      ProguardConfigurationParser parser =
          new ProguardConfigurationParser(new DexItemFactory(), reporter);
      parser.parse(
          createConfigurationForTesting(
              ImmutableList.of(directive + " @" + includeFile.toAbsolutePath())));
      ProguardConfiguration configuration = parser.getConfig();
      assertEquals(packageObfuscationMode, configuration.getPackageObfuscationMode());
      assertEquals("", configuration.getPackagePrefix());

      List<ProguardConfigurationRule> rules = configuration.getRules();
      assertEquals(1, rules.size());

      ProguardConfigurationRule rule = rules.get(0);
      assertEquals(ProguardKeepRuleType.KEEP.toString(), rule.typeString());
      assertEquals("*", rule.getClassNames().toString());
    }
  }

  @Test
  public void negatedMemberTypeTest() throws IOException {
    Path proguardConfigurationFile = writeTextToTempFile("-keepclassmembers class ** { !int x; }");
    try {
      new ProguardConfigurationParser(new DexItemFactory(), reporter)
          .parse(proguardConfigurationFile);
      fail("Expected to fail since the type name cannot be negated.");
    } catch (AbortException e) {
      checkDiagnostics(
          handler.errors,
          proguardConfigurationFile,
          1,
          30,
          "Unexpected character '!': "
              + "The negation character can only be used to negate access flags");
    }
  }

  @Test
  public void parseIncludeCode() throws Exception {
    ProguardConfigurationParser parser;
    parser = new ProguardConfigurationParser(new DexItemFactory(), reporter);
    Path proguardConfig = writeTextToTempFile("-keep,includecode class A { method(); }");
    parser.parse(proguardConfig);
    assertEquals(1, parser.getConfig().getRules().size());
    assertEquals(1, handler.infos.size());
    checkDiagnostics(handler.infos, proguardConfig, 1, 7, "Ignoring modifier", "includecode");
  }
}
