1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "SourceXmlPullParser.h" 18#include "BindingXmlPullParser.h" 19 20#include <gtest/gtest.h> 21#include <sstream> 22#include <string> 23 24namespace aapt { 25 26constexpr const char16_t* kAndroidNamespaceUri = u"http://schemas.android.com/apk/res/android"; 27 28TEST(BindingXmlPullParserTest, SubstituteBindingExpressionsWithTag) { 29 std::stringstream input; 30 input << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" 31 << "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" 32 << " xmlns:bind=\"http://schemas.android.com/apk/binding\"\n" 33 << " android:id=\"@+id/content\">\n" 34 << " <variable name=\"user\" type=\"com.android.test.User\"/>\n" 35 << " <TextView android:text=\"@{user.name}\" android:layout_width=\"wrap_content\"\n" 36 << " android:layout_height=\"wrap_content\"/>\n" 37 << "</LinearLayout>\n"; 38 std::shared_ptr<XmlPullParser> sourceParser = std::make_shared<SourceXmlPullParser>(input); 39 BindingXmlPullParser parser(sourceParser); 40 41 ASSERT_EQ(XmlPullParser::Event::kStartNamespace, parser.next()); 42 EXPECT_EQ(std::u16string(u"http://schemas.android.com/apk/res/android"), 43 parser.getNamespaceUri()); 44 45 ASSERT_EQ(XmlPullParser::Event::kStartElement, parser.next()); 46 EXPECT_EQ(std::u16string(u"LinearLayout"), parser.getElementName()); 47 48 while (parser.next() == XmlPullParser::Event::kText) {} 49 50 ASSERT_EQ(XmlPullParser::Event::kStartElement, parser.getEvent()); 51 EXPECT_EQ(std::u16string(u"TextView"), parser.getElementName()); 52 53 ASSERT_EQ(3u, parser.getAttributeCount()); 54 const auto endAttr = parser.endAttributes(); 55 EXPECT_NE(endAttr, parser.findAttribute(kAndroidNamespaceUri, u"layout_width")); 56 EXPECT_NE(endAttr, parser.findAttribute(kAndroidNamespaceUri, u"layout_height")); 57 EXPECT_NE(endAttr, parser.findAttribute(kAndroidNamespaceUri, u"tag")); 58 59 while (parser.next() == XmlPullParser::Event::kText) {} 60 61 ASSERT_EQ(XmlPullParser::Event::kEndElement, parser.getEvent()); 62 63 while (parser.next() == XmlPullParser::Event::kText) {} 64 65 ASSERT_EQ(XmlPullParser::Event::kEndElement, parser.getEvent()); 66 ASSERT_EQ(XmlPullParser::Event::kEndNamespace, parser.next()); 67} 68 69TEST(BindingXmlPullParserTest, GenerateVariableDeclarations) { 70 std::stringstream input; 71 input << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" 72 << "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" 73 << " xmlns:bind=\"http://schemas.android.com/apk/binding\"\n" 74 << " android:id=\"@+id/content\">\n" 75 << " <variable name=\"user\" type=\"com.android.test.User\"/>\n" 76 << "</LinearLayout>\n"; 77 std::shared_ptr<XmlPullParser> sourceParser = std::make_shared<SourceXmlPullParser>(input); 78 BindingXmlPullParser parser(sourceParser); 79 80 while (XmlPullParser::isGoodEvent(parser.next())) { 81 ASSERT_NE(XmlPullParser::Event::kBadDocument, parser.getEvent()); 82 } 83 84 std::stringstream output; 85 ASSERT_TRUE(parser.writeToFile(output)); 86 87 std::string result = output.str(); 88 EXPECT_NE(std::string::npos, 89 result.find("<entries name=\"user\" type=\"com.android.test.User\"/>")); 90} 91 92TEST(BindingXmlPullParserTest, FailOnMissingNameOrTypeInVariableDeclaration) { 93 std::stringstream input; 94 input << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" 95 << "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" 96 << " xmlns:bind=\"http://schemas.android.com/apk/binding\"\n" 97 << " android:id=\"@+id/content\">\n" 98 << " <variable name=\"user\"/>\n" 99 << "</LinearLayout>\n"; 100 std::shared_ptr<XmlPullParser> sourceParser = std::make_shared<SourceXmlPullParser>(input); 101 BindingXmlPullParser parser(sourceParser); 102 103 while (XmlPullParser::isGoodEvent(parser.next())) {} 104 105 EXPECT_EQ(XmlPullParser::Event::kBadDocument, parser.getEvent()); 106 EXPECT_FALSE(parser.getLastError().empty()); 107} 108 109 110} // namespace aapt 111