1/* 2 * Copyright (C) 2016 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 "DominatorTree.h" 18 19#include <sstream> 20#include <string> 21#include <vector> 22 23#include "test/Test.h" 24#include "util/Util.h" 25 26namespace aapt { 27 28namespace { 29 30class PrettyPrinter : public DominatorTree::Visitor { 31 public: 32 explicit PrettyPrinter(const int indent = 2) : indent_(indent) {} 33 34 void VisitTree(const std::string& product, 35 DominatorTree::Node* root) override { 36 for (auto& child : root->children()) { 37 VisitNode(child.get(), 0); 38 } 39 } 40 41 std::string ToString(DominatorTree* tree) { 42 buffer_.str(""); 43 buffer_.clear(); 44 tree->Accept(this); 45 return buffer_.str(); 46 } 47 48 private: 49 void VisitConfig(const DominatorTree::Node* node, const int indent) { 50 auto config_string = node->value()->config.toString(); 51 buffer_ << std::string(indent, ' ') 52 << (config_string.isEmpty() ? "<default>" : config_string) 53 << std::endl; 54 } 55 56 void VisitNode(const DominatorTree::Node* node, const int indent) { 57 VisitConfig(node, indent); 58 for (const auto& child : node->children()) { 59 VisitNode(child.get(), indent + indent_); 60 } 61 } 62 63 std::stringstream buffer_; 64 const int indent_ = 2; 65}; 66 67} // namespace 68 69TEST(DominatorTreeTest, DefaultDominatesEverything) { 70 const ConfigDescription default_config = {}; 71 const ConfigDescription land_config = test::ParseConfigOrDie("land"); 72 const ConfigDescription sw600dp_land_config = 73 test::ParseConfigOrDie("sw600dp-land-v13"); 74 75 std::vector<std::unique_ptr<ResourceConfigValue>> configs; 76 configs.push_back(util::make_unique<ResourceConfigValue>(default_config, "")); 77 configs.push_back(util::make_unique<ResourceConfigValue>(land_config, "")); 78 configs.push_back( 79 util::make_unique<ResourceConfigValue>(sw600dp_land_config, "")); 80 81 DominatorTree tree(configs); 82 PrettyPrinter printer; 83 84 std::string expected = 85 "<default>\n" 86 " land\n" 87 " sw600dp-land-v13\n"; 88 EXPECT_EQ(expected, printer.ToString(&tree)); 89} 90 91TEST(DominatorTreeTest, ProductsAreDominatedSeparately) { 92 const ConfigDescription default_config = {}; 93 const ConfigDescription land_config = test::ParseConfigOrDie("land"); 94 const ConfigDescription sw600dp_land_config = 95 test::ParseConfigOrDie("sw600dp-land-v13"); 96 97 std::vector<std::unique_ptr<ResourceConfigValue>> configs; 98 configs.push_back(util::make_unique<ResourceConfigValue>(default_config, "")); 99 configs.push_back(util::make_unique<ResourceConfigValue>(land_config, "")); 100 configs.push_back( 101 util::make_unique<ResourceConfigValue>(default_config, "phablet")); 102 configs.push_back( 103 util::make_unique<ResourceConfigValue>(sw600dp_land_config, "phablet")); 104 105 DominatorTree tree(configs); 106 PrettyPrinter printer; 107 108 std::string expected = 109 "<default>\n" 110 " land\n" 111 "<default>\n" 112 " sw600dp-land-v13\n"; 113 EXPECT_EQ(expected, printer.ToString(&tree)); 114} 115 116TEST(DominatorTreeTest, MoreSpecificConfigurationsAreDominated) { 117 const ConfigDescription default_config = {}; 118 const ConfigDescription en_config = test::ParseConfigOrDie("en"); 119 const ConfigDescription en_v21_config = test::ParseConfigOrDie("en-v21"); 120 const ConfigDescription ldrtl_config = test::ParseConfigOrDie("ldrtl-v4"); 121 const ConfigDescription ldrtl_xhdpi_config = 122 test::ParseConfigOrDie("ldrtl-xhdpi-v4"); 123 const ConfigDescription sw300dp_config = 124 test::ParseConfigOrDie("sw300dp-v13"); 125 const ConfigDescription sw540dp_config = 126 test::ParseConfigOrDie("sw540dp-v14"); 127 const ConfigDescription sw600dp_config = 128 test::ParseConfigOrDie("sw600dp-v14"); 129 const ConfigDescription sw720dp_config = 130 test::ParseConfigOrDie("sw720dp-v13"); 131 const ConfigDescription v20_config = test::ParseConfigOrDie("v20"); 132 133 std::vector<std::unique_ptr<ResourceConfigValue>> configs; 134 configs.push_back(util::make_unique<ResourceConfigValue>(default_config, "")); 135 configs.push_back(util::make_unique<ResourceConfigValue>(en_config, "")); 136 configs.push_back(util::make_unique<ResourceConfigValue>(en_v21_config, "")); 137 configs.push_back(util::make_unique<ResourceConfigValue>(ldrtl_config, "")); 138 configs.push_back( 139 util::make_unique<ResourceConfigValue>(ldrtl_xhdpi_config, "")); 140 configs.push_back(util::make_unique<ResourceConfigValue>(sw300dp_config, "")); 141 configs.push_back(util::make_unique<ResourceConfigValue>(sw540dp_config, "")); 142 configs.push_back(util::make_unique<ResourceConfigValue>(sw600dp_config, "")); 143 configs.push_back(util::make_unique<ResourceConfigValue>(sw720dp_config, "")); 144 configs.push_back(util::make_unique<ResourceConfigValue>(v20_config, "")); 145 146 DominatorTree tree(configs); 147 PrettyPrinter printer; 148 149 std::string expected = 150 "<default>\n" 151 " en\n" 152 " en-v21\n" 153 " ldrtl-v4\n" 154 " ldrtl-xhdpi-v4\n" 155 " sw300dp-v13\n" 156 " sw540dp-v14\n" 157 " sw600dp-v14\n" 158 " sw720dp-v13\n" 159 " v20\n"; 160 EXPECT_EQ(expected, printer.ToString(&tree)); 161} 162 163} // namespace aapt 164