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 26 namespace aapt { 27 28 namespace { 29 30 class 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 69 TEST(DominatorTreeTest, DefaultDominatesEverything) { 70 const ConfigDescription default_config = {}; 71 const ConfigDescription land_config = test::ParseConfigOrDie("land"); 72 const ConfigDescription sw600dp_land_config = test::ParseConfigOrDie("sw600dp-land-v13"); 73 74 std::vector<std::unique_ptr<ResourceConfigValue>> configs; 75 configs.push_back(util::make_unique<ResourceConfigValue>(default_config, "")); 76 configs.push_back(util::make_unique<ResourceConfigValue>(land_config, "")); 77 configs.push_back(util::make_unique<ResourceConfigValue>(sw600dp_land_config, "")); 78 79 DominatorTree tree(configs); 80 PrettyPrinter printer; 81 82 std::string expected = 83 "<default>\n" 84 " land\n" 85 " sw600dp-land-v13\n"; 86 EXPECT_EQ(expected, printer.ToString(&tree)); 87 } 88 89 TEST(DominatorTreeTest, ProductsAreDominatedSeparately) { 90 const ConfigDescription default_config = {}; 91 const ConfigDescription land_config = test::ParseConfigOrDie("land"); 92 const ConfigDescription sw600dp_land_config = test::ParseConfigOrDie("sw600dp-land-v13"); 93 94 std::vector<std::unique_ptr<ResourceConfigValue>> configs; 95 configs.push_back(util::make_unique<ResourceConfigValue>(default_config, "")); 96 configs.push_back(util::make_unique<ResourceConfigValue>(land_config, "")); 97 configs.push_back(util::make_unique<ResourceConfigValue>(default_config, "phablet")); 98 configs.push_back(util::make_unique<ResourceConfigValue>(sw600dp_land_config, "phablet")); 99 100 DominatorTree tree(configs); 101 PrettyPrinter printer; 102 103 std::string expected = 104 "<default>\n" 105 " land\n" 106 "<default>\n" 107 " sw600dp-land-v13\n"; 108 EXPECT_EQ(expected, printer.ToString(&tree)); 109 } 110 111 TEST(DominatorTreeTest, MoreSpecificConfigurationsAreDominated) { 112 const ConfigDescription default_config = {}; 113 const ConfigDescription en_config = test::ParseConfigOrDie("en"); 114 const ConfigDescription en_v21_config = test::ParseConfigOrDie("en-v21"); 115 const ConfigDescription ldrtl_config = test::ParseConfigOrDie("ldrtl-v4"); 116 const ConfigDescription ldrtl_xhdpi_config = test::ParseConfigOrDie("ldrtl-xhdpi-v4"); 117 const ConfigDescription sw300dp_config = test::ParseConfigOrDie("sw300dp-v13"); 118 const ConfigDescription sw540dp_config = test::ParseConfigOrDie("sw540dp-v14"); 119 const ConfigDescription sw600dp_config = test::ParseConfigOrDie("sw600dp-v14"); 120 const ConfigDescription sw720dp_config = test::ParseConfigOrDie("sw720dp-v13"); 121 const ConfigDescription v20_config = test::ParseConfigOrDie("v20"); 122 123 std::vector<std::unique_ptr<ResourceConfigValue>> configs; 124 configs.push_back(util::make_unique<ResourceConfigValue>(default_config, "")); 125 configs.push_back(util::make_unique<ResourceConfigValue>(en_config, "")); 126 configs.push_back(util::make_unique<ResourceConfigValue>(en_v21_config, "")); 127 configs.push_back(util::make_unique<ResourceConfigValue>(ldrtl_config, "")); 128 configs.push_back(util::make_unique<ResourceConfigValue>(ldrtl_xhdpi_config, "")); 129 configs.push_back(util::make_unique<ResourceConfigValue>(sw300dp_config, "")); 130 configs.push_back(util::make_unique<ResourceConfigValue>(sw540dp_config, "")); 131 configs.push_back(util::make_unique<ResourceConfigValue>(sw600dp_config, "")); 132 configs.push_back(util::make_unique<ResourceConfigValue>(sw720dp_config, "")); 133 configs.push_back(util::make_unique<ResourceConfigValue>(v20_config, "")); 134 135 DominatorTree tree(configs); 136 PrettyPrinter printer; 137 138 std::string expected = 139 "<default>\n" 140 " ldrtl-v4\n" 141 " ldrtl-xhdpi-v4\n" 142 " sw300dp-v13\n" 143 " sw540dp-v14\n" 144 " sw600dp-v14\n" 145 " sw720dp-v13\n" 146 " v20\n" 147 "en\n" 148 " en-v21\n"; 149 EXPECT_EQ(expected, printer.ToString(&tree)); 150 } 151 152 TEST(DominatorTreeTest, LocalesAreNeverDominated) { 153 const ConfigDescription fr_config = test::ParseConfigOrDie("fr"); 154 const ConfigDescription fr_rCA_config = test::ParseConfigOrDie("fr-rCA"); 155 const ConfigDescription fr_rFR_config = test::ParseConfigOrDie("fr-rFR"); 156 157 std::vector<std::unique_ptr<ResourceConfigValue>> configs; 158 configs.push_back(util::make_unique<ResourceConfigValue>(ConfigDescription::DefaultConfig(), "")); 159 configs.push_back(util::make_unique<ResourceConfigValue>(fr_config, "")); 160 configs.push_back(util::make_unique<ResourceConfigValue>(fr_rCA_config, "")); 161 configs.push_back(util::make_unique<ResourceConfigValue>(fr_rFR_config, "")); 162 163 DominatorTree tree(configs); 164 PrettyPrinter printer; 165 166 std::string expected = 167 "<default>\n" 168 "fr\n" 169 "fr-rCA\n" 170 "fr-rFR\n"; 171 EXPECT_EQ(expected, printer.ToString(&tree)); 172 } 173 174 } // namespace aapt 175