/**
  * Assert the error message is correct.
  *
  * @param messages a collection of Messages
  * @param expectedText the text the single gradle message should have.
  * @param expectedLine the 1-based line
  * @param expectedColumn the 1-based column.
  */
 private void assertHasCorrectErrorMessage(
     @NonNull Collection<Message> messages,
     @NonNull String expectedText,
     int expectedLine,
     int expectedColumn) {
   assertEquals("[message count]", 1, messages.size());
   Message message = messages.iterator().next();
   assertEquals("[source file position count]", 1, message.getSourceFilePositions().size());
   SourceFilePosition position = message.getSourceFilePositions().get(0);
   assertEquals("[file path]", sourceFilePath, position.getFile().toString());
   assertEquals("[message severity]", Message.Kind.ERROR, message.getKind());
   assertEquals("[message text]", expectedText, message.getText());
   assertEquals("[position line]", expectedLine, position.getPosition().getStartLine() + 1);
   assertEquals("[position column]", expectedColumn, position.getPosition().getStartColumn() + 1);
 }
  public void testRedirectFileLinksOutput() throws Exception {
    if (!setupSdkHome()) {
      System.out.println("Skipping testRedirectFileLinksOutput because sdk-common was not found");
      return;
    }

    // Need file to be named (exactly) values.xml
    File tempDir = Files.createTempDir();
    File layoutDir = new File(tempDir, "layout-land");
    layoutDir.mkdirs();
    sourceFile = new File(layoutDir, "main.xml");
    sourceFilePath = sourceFile.getAbsolutePath();

    writeToFile(
        "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
            + "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
            + "    android:orientation=\"vertical\"\n"
            + "    android:layout_width=\"fill_parent\"\n"
            + "    android:layout_height=\"fill_parent\"\n"
            + "    >\n"
            + "<TextView\n"
            + "    android:layout_width=\"fill_parent\"\n"
            + "    android:layout_height=\"wrap_content\"\n"
            + "    android:text=\"Test App - Basic\"\n"
            + "    android:id=\"@+id/text\"\n"
            + "    />\n"
            + "</LinearLayout>\n"
            + "\n"
            + "<!-- From: file:src/test/resources/testData/resources/incMergeData/filesVsValues/main/layout/main.xml -->");

    String messageText = "Random error message here";
    String err = sourceFilePath + ":4: error: Error: " + messageText;
    Collection<Message> messages = parser.parseToolOutput(err);
    assertEquals("[message count]", 1, messages.size());
    Message message = messages.iterator().next();
    assertNotNull(message);

    // NOT sourceFilePath; should be translated back from source comment
    String expected =
        new File(
                "src/test/resources/testData/resources/incMergeData/filesVsValues/main/layout/main.xml")
            .getAbsolutePath();
    assertEquals("[file path]", expected, getSystemIndependentSourcePath(message));
    assertEquals("[message severity]", Message.Kind.ERROR, message.getKind());
    assertEquals("[message text]", messageText, message.getText());
    assertEquals(
        "[position line]",
        4,
        message.getSourceFilePositions().get(0).getPosition().getStartLine() + 1);
    // assertEquals("[position column]", 35, message.getColumn());

    // TODO: Test encoding issues (e.g. & in path where the XML source comment would be &amp;
    // instead)
  }
  @NonNull
  private static String toString(@NonNull List<Message> messages) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0, n = messages.size(); i < n; i++) {
      Message message = messages.get(i);
      sb.append(Integer.toString(i)).append(':').append(' ');
      sb.append(message.getKind().toString().toLowerCase(Locale.US)).append(':'); // INFO => Info
      sb.append(message.getText());
      if (!message.getSourceFilePositions().isEmpty()
          && !message
              .getSourceFilePositions()
              .get(0)
              .getPosition()
              .equals(SourcePosition.UNKNOWN)) {
        sb.append('\n');
        sb.append('\t');
        sb.append(message.getSourceFilePositions().get(0).toString());
      }
      sb.append('\n');
    }

    return sb.toString();
  }
  public void testRedirectValueLinksOutput() throws Exception {
    if (!setupSdkHome()) {
      System.out.println("Skipping testRedirectValueLinksOutput because sdk-common was not found");
      return;
    }

    // Need file to be named (exactly) values.xml
    File tempDir = Files.createTempDir();
    File valueDir = new File(tempDir, "values-en");
    valueDir.mkdirs();
    sourceFile =
        new File(valueDir, "values.xml"); // Keep in sync with MergedResourceWriter.FN_VALUES_XML
    sourceFilePath = sourceFile.getAbsolutePath();

    writeToFile(
        "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
            + "<resources xmlns:ns1=\"urn:oasis:names:tc:xliff:document:1.2\">\n"
            + "\n"
            + "    <!-- From: src/test/resources/testData/resources/baseSet/values/values.xml -->\n"
            + "    <string-array name=\"string_array\" translatable=\"false\">\n"
            + "        <item/> <!-- 0 -->\n"
            + "        <item/> <!-- 1 -->\n"
            + "        <item>ABC</item> <!-- 2 -->\n"
            + "        <item>DEF</item> <!-- 3 -->\n"
            + "        <item>GHI</item> <!-- 4 -->\n"
            + "        <item>JKL</item> <!-- 5 -->\n"
            + "        <item>MNO</item> <!-- 6 -->\n"
            + "        <item>PQRS</item> <!-- 7 -->\n"
            + "        <item>TUV</item> <!-- 8 -->\n"
            + "        <item>WXYZ</item> <!-- 9 -->\n"
            + "    </string-array>\n"
            + "\n"
            + "    <attr name=\"dimen_attr\" format=\"dimension\" />\n"
            + "    <attr name=\"enum_attr\">\n"
            + "        <enum name=\"normal\" value=\"0\" />\n"
            + "        <enum name=\"sans\" value=\"1\" />\n"
            + "        <enum name=\"serif\" value=\"2\" />\n"
            + "        <enum name=\"monospace\" value=\"3\" />\n"
            + "    </attr>\n"
            + "    <attr name=\"flag_attr\">\n"
            + "        <flag name=\"normal\" value=\"0\" />\n"
            + "        <flag name=\"bold\" value=\"1\" />\n"
            + "        <flag name=\"italic\" value=\"2\" />\n"
            + "    </attr>\n"
            + "    <attr name=\"string_attr\" format=\"string\" />\n"
            + "    <!-- From: src/test/resources/testData/resources/baseMerge/overlay/values/values.xml -->\n"
            + "    <color name=\"color\">#FFFFFFFF</color>\n"
            + "    <!-- From: src/test/resources/testData/resources/baseSet/values/values.xml -->\n"
            + "    <declare-styleable name=\"declare_styleable\">\n"
            + "\n"
            + "        <!-- ============== -->\n"
            + "        <!-- Generic styles -->\n"
            + "        <!-- ============== -->\n"
            + "        <eat-comment />\n"
            + "\n"
            + "        <!-- Default color of foreground imagery. -->\n"
            + "        <attr name=\"blah\" format=\"color\" />\n"
            + "        <!-- Default color of foreground imagery on an inverted background. -->\n"
            + "        <attr name=\"android:colorForegroundInverse\" />\n"
            + "    </declare-styleable>\n"
            + "\n"
            + "    <dimen name=\"dimen\">164dp</dimen>\n"
            + "\n"
            + "    <drawable name=\"color_drawable\">#ffffffff</drawable>\n"
            + "    <drawable name=\"drawable_ref\">@drawable/stat_notify_sync_anim0</drawable>\n"
            + "\n"
            + "    <item name=\"item_id\" type=\"id\"/>\n"
            + "\n"
            + "    <integer name=\"integer\">75</integer>\n"
            + "    <!-- From: src/test/resources/testData/resources/baseMerge/overlay/values/values.xml -->\n"
            + "    <item name=\"file_replaced_by_alias\" type=\"layout\">@layout/ref</item>\n"
            + "    <!-- From: src/test/resources/testData/resources/baseSet/values/values.xml -->\n"
            + "    <item name=\"layout_ref\" type=\"layout\">@layout/ref</item>\n"
            + "    <!-- From: src/test/resources/testData/resources/baseMerge/overlay/values/values.xml -->\n"
            + "    <string name=\"basic_string\">overlay_string</string>\n"
            + "    <!-- From: src/test/resources/testData/resources/baseSet/values/values.xml -->\n"
            + "    <string name=\"styled_string\">Forgot your username or password\\?\\nVisit <b>google.com/accounts/recovery</b>.</string>\n"
            + "    <string name=\"xliff_string\"><ns1:g id=\"number\" example=\"123\">%1$s</ns1:g><ns1:g id=\"unit\" example=\"KB\">%2$s</ns1:g></string>\n"
            + "\n"
            + "    <style name=\"style\" parent=\"@android:style/Holo.Light\">\n"
            + "        <item name=\"android:singleLine\">true</item>\n"
            + "        <item name=\"android:textAppearance\">@style/TextAppearance.WindowTitle</item>\n"
            + "        <item name=\"android:shadowColor\">#BB000000</item>\n"
            + "        <item name=\"android:shadowRadius\">2.75</item>\n"
            + "        <item name=\"foo\">foo</item>\n"
            + "    </style>\n"
            + "\n"
            + "</resources>\n");

    String messageText =
        "String types not allowed (at 'drawable_ref' with value '@drawable/stat_notify_sync_anim0').";
    String err = sourceFilePath + ":46: error: Error: " + messageText;
    Collection<Message> messages = parser.parseToolOutput(err);
    assertEquals(1, messages.size());

    assertEquals("[message count]", 1, messages.size());
    Message message = messages.iterator().next();

    assertNotNull(message);

    // NOT sourceFilePath; should be translated back from source comment
    assertEquals(
        new File("src/test/resources/testData/resources/baseSet/values/values.xml")
            .getAbsolutePath(),
        getSystemIndependentSourcePath(message));

    assertEquals("[message severity]", Message.Kind.ERROR, message.getKind());
    assertEquals("[message text]", messageText, message.getText());
    assertEquals(1, message.getSourceFilePositions().size());
    SourcePosition pos = message.getSourceFilePositions().get(0).getPosition();
    assertEquals("[position line]", 9, pos.getStartLine() + 1);
    assertEquals("[position column]", 35, pos.getStartColumn() + 1);
  }