Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 150bafd2 authored by Ryan Mitchell's avatar Ryan Mitchell Committed by Android (Google) Code Review
Browse files

Merge "AAPT2: Fix quoted text in res/xml assets" into pi-dev

parents 9115d371 0dcb20c7
Loading
Loading
Loading
Loading
+15 −7
Original line number Original line Diff line number Diff line
@@ -79,23 +79,31 @@ class XmlFlattenerVisitor : public xml::ConstVisitor {
  }
  }


  void Visit(const xml::Text* node) override {
  void Visit(const xml::Text* node) override {
    if (util::TrimWhitespace(node->text).empty()) {
    std::string text = util::TrimWhitespace(node->text).to_string();

    // Skip whitespace only text nodes.
    // Skip whitespace only text nodes.
    if (text.empty()) {
      return;
      return;
    }
    }


    // Compact leading and trailing whitespace into a single space
    if (isspace(node->text[0])) {
      text = ' ' + text;
    }
    if (isspace(node->text[node->text.length() - 1])) {
      text = text + ' ';
    }

    ChunkWriter writer(buffer_);
    ChunkWriter writer(buffer_);
    ResXMLTree_node* flat_node = writer.StartChunk<ResXMLTree_node>(RES_XML_CDATA_TYPE);
    ResXMLTree_node* flat_node = writer.StartChunk<ResXMLTree_node>(RES_XML_CDATA_TYPE);
    flat_node->lineNumber = util::HostToDevice32(node->line_number);
    flat_node->lineNumber = util::HostToDevice32(node->line_number);
    flat_node->comment.index = util::HostToDevice32(-1);
    flat_node->comment.index = util::HostToDevice32(-1);


    ResXMLTree_cdataExt* flat_text = writer.NextBlock<ResXMLTree_cdataExt>();

    // Process plain strings to make sure they get properly escaped.
    // Process plain strings to make sure they get properly escaped.
    StringBuilder builder;
    text = StringBuilder(true /*preserve_spaces*/).AppendText(text).to_string();
    builder.AppendText(node->text);
    AddString(builder.to_string(), kLowPriority, &flat_text->data);


    ResXMLTree_cdataExt* flat_text = writer.NextBlock<ResXMLTree_cdataExt>();
    AddString(text, kLowPriority, &flat_text->data);
    writer.Finish();
    writer.Finish();
  }
  }


+159 −0
Original line number Original line Diff line number Diff line
@@ -286,6 +286,165 @@ TEST_F(XmlFlattenerTest, ProcessEscapedStrings) {
  EXPECT_THAT(tree.getText(&len), StrEq(u"\\d{5}"));
  EXPECT_THAT(tree.getText(&len), StrEq(u"\\d{5}"));
}
}


TEST_F(XmlFlattenerTest, ProcessQuotes) {
  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(
      R"(<root>
          <item>Regular text</item>
          <item>"Text in double quotes"</item>
          <item>'Text in single quotes'</item>
          <item>Text containing "double quotes"</item>
          <item>Text containing 'single quotes'</item>
      </root>)");

  size_t len;
  android::ResXMLTree tree;

  XmlFlattenerOptions options;
  ASSERT_TRUE(Flatten(doc.get(), &tree, options));

  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
  EXPECT_THAT(tree.getText(&len), StrEq(u"Regular text"));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));

  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
  EXPECT_THAT(tree.getText(&len), StrEq(u"\"Text in double quotes\""));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));

  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
  EXPECT_THAT(tree.getElementNamespace(&len), IsNull());
  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
  EXPECT_THAT(tree.getText(&len), StrEq(u"'Text in single quotes'"));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));

  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
  EXPECT_THAT(tree.getText(&len), StrEq(u"Text containing \"double quotes\""));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));

  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
  EXPECT_THAT(tree.getText(&len), StrEq(u"Text containing 'single quotes'"));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));

  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_DOCUMENT));
}

TEST_F(XmlFlattenerTest, ProcessWhitepspace) {
  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(
      R"(<root>
          <item>   Compact   Spaces   </item>
          <item>
                 A
          </item>
          <item>B   </item>
          <item>C </item>
          <item> D  </item>
          <item>   E</item>
          <item> F</item>
          <item>  G </item>
          <item> H </item>
<item>
I
</item>
<item>

   J

</item>
          <item>
          </item>
      </root>)");

  size_t len;
  android::ResXMLTree tree;

  XmlFlattenerOptions options;
  ASSERT_TRUE(Flatten(doc.get(), &tree, options));

  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
  EXPECT_THAT(tree.getText(&len), StrEq(u" Compact   Spaces "));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));

  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
  EXPECT_THAT(tree.getText(&len), StrEq(u" A "));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));

  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
  EXPECT_THAT(tree.getText(&len), StrEq(u"B "));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));

  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
  EXPECT_THAT(tree.getText(&len), StrEq(u"C "));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));

  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
  EXPECT_THAT(tree.getText(&len), StrEq(u" D "));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));

  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
  EXPECT_THAT(tree.getText(&len), StrEq(u" E"));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));

  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
  EXPECT_THAT(tree.getText(&len), StrEq(u" F"));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));

  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
  EXPECT_THAT(tree.getText(&len), StrEq(u" G "));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));

  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
  EXPECT_THAT(tree.getText(&len), StrEq(u" H "));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));

  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
  EXPECT_THAT(tree.getText(&len), StrEq(u" I "));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));

  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
  EXPECT_THAT(tree.getText(&len), StrEq(u" J "));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));

  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));

  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_DOCUMENT));
}

TEST_F(XmlFlattenerTest, FlattenRawValueOnlyMakesCompiledValueToo) {
TEST_F(XmlFlattenerTest, FlattenRawValueOnlyMakesCompiledValueToo) {
  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<element foo="bar" />)");
  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<element foo="bar" />)");