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 #ifndef AAPT_TEST_COMMON_H 18 #define AAPT_TEST_COMMON_H 19 20 #include <iostream> 21 22 #include "android-base/logging.h" 23 #include "android-base/macros.h" 24 #include "androidfw/StringPiece.h" 25 #include "gmock/gmock.h" 26 #include "gtest/gtest.h" 27 28 #include "ConfigDescription.h" 29 #include "Debug.h" 30 #include "ResourceTable.h" 31 #include "ResourceUtils.h" 32 #include "ResourceValues.h" 33 #include "ValueVisitor.h" 34 #include "io/File.h" 35 #include "process/IResourceTableConsumer.h" 36 37 namespace aapt { 38 namespace test { 39 40 IDiagnostics* GetDiagnostics(); 41 42 inline ResourceName ParseNameOrDie(const android::StringPiece& str) { 43 ResourceNameRef ref; 44 CHECK(ResourceUtils::ParseResourceName(str, &ref)) << "invalid resource name"; 45 return ref.ToResourceName(); 46 } 47 48 inline ConfigDescription ParseConfigOrDie(const android::StringPiece& str) { 49 ConfigDescription config; 50 CHECK(ConfigDescription::Parse(str, &config)) << "invalid configuration"; 51 return config; 52 } 53 54 template <typename T = Value> 55 T* GetValueForConfigAndProduct(ResourceTable* table, const android::StringPiece& res_name, 56 const ConfigDescription& config, 57 const android::StringPiece& product) { 58 Maybe<ResourceTable::SearchResult> result = table->FindResource(ParseNameOrDie(res_name)); 59 if (result) { 60 ResourceConfigValue* config_value = result.value().entry->FindValue(config, product); 61 if (config_value) { 62 return ValueCast<T>(config_value->value.get()); 63 } 64 } 65 return nullptr; 66 } 67 68 template <> 69 Value* GetValueForConfigAndProduct<Value>(ResourceTable* table, 70 const android::StringPiece& res_name, 71 const ConfigDescription& config, 72 const android::StringPiece& product); 73 74 template <typename T = Value> 75 T* GetValueForConfig(ResourceTable* table, const android::StringPiece& res_name, 76 const ConfigDescription& config) { 77 return GetValueForConfigAndProduct<T>(table, res_name, config, {}); 78 } 79 80 template <typename T = Value> 81 T* GetValue(ResourceTable* table, const android::StringPiece& res_name) { 82 return GetValueForConfig<T>(table, res_name, {}); 83 } 84 85 class TestFile : public io::IFile { 86 public: 87 explicit TestFile(const android::StringPiece& path) : source_(path) {} 88 89 std::unique_ptr<io::IData> OpenAsData() override { 90 return {}; 91 } 92 93 const Source& GetSource() const override { 94 return source_; 95 } 96 97 private: 98 DISALLOW_COPY_AND_ASSIGN(TestFile); 99 100 Source source_; 101 }; 102 103 } // namespace test 104 105 // Workaround gtest bug (https://github.com/google/googletest/issues/443) 106 // that does not select base class operator<< for derived class T. 107 template <typename T> 108 typename std::enable_if<std::is_base_of<Value, T>::value, std::ostream&>::type operator<<( 109 std::ostream& out, const T& value) { 110 value.Print(&out); 111 return out; 112 } 113 114 template std::ostream& operator<<<Item>(std::ostream&, const Item&); 115 template std::ostream& operator<<<Reference>(std::ostream&, const Reference&); 116 template std::ostream& operator<<<Id>(std::ostream&, const Id&); 117 template std::ostream& operator<<<RawString>(std::ostream&, const RawString&); 118 template std::ostream& operator<<<String>(std::ostream&, const String&); 119 template std::ostream& operator<<<StyledString>(std::ostream&, const StyledString&); 120 template std::ostream& operator<<<FileReference>(std::ostream&, const FileReference&); 121 template std::ostream& operator<<<BinaryPrimitive>(std::ostream&, const BinaryPrimitive&); 122 template std::ostream& operator<<<Attribute>(std::ostream&, const Attribute&); 123 template std::ostream& operator<<<Style>(std::ostream&, const Style&); 124 template std::ostream& operator<<<Array>(std::ostream&, const Array&); 125 template std::ostream& operator<<<Plural>(std::ostream&, const Plural&); 126 127 // Add a print method to Maybe. 128 template <typename T> 129 void PrintTo(const Maybe<T>& value, std::ostream* out) { 130 if (value) { 131 *out << ::testing::PrintToString(value.value()); 132 } else { 133 *out << "Nothing"; 134 } 135 } 136 137 namespace test { 138 139 MATCHER_P(StrEq, a, 140 std::string(negation ? "isn't" : "is") + " equal to " + 141 ::testing::PrintToString(android::StringPiece16(a))) { 142 return android::StringPiece16(arg) == a; 143 } 144 145 class ValueEq { 146 public: 147 template <typename arg_type> 148 class BaseImpl : public ::testing::MatcherInterface<arg_type> { 149 BaseImpl(const BaseImpl&) = default; 150 151 void DescribeTo(::std::ostream* os) const override { 152 *os << "is equal to " << *expected_; 153 } 154 155 void DescribeNegationTo(::std::ostream* os) const override { 156 *os << "is not equal to " << *expected_; 157 } 158 159 protected: 160 BaseImpl(const Value* expected) : expected_(expected) { 161 } 162 163 const Value* expected_; 164 }; 165 166 template <typename T, bool> 167 class Impl {}; 168 169 template <typename T> 170 class Impl<T, false> : public ::testing::MatcherInterface<T> { 171 public: 172 explicit Impl(const Value* expected) : expected_(expected) { 173 } 174 175 bool MatchAndExplain(T x, ::testing::MatchResultListener* listener) const override { 176 return expected_->Equals(&x); 177 } 178 179 void DescribeTo(::std::ostream* os) const override { 180 *os << "is equal to " << *expected_; 181 } 182 183 void DescribeNegationTo(::std::ostream* os) const override { 184 *os << "is not equal to " << *expected_; 185 } 186 187 private: 188 DISALLOW_COPY_AND_ASSIGN(Impl); 189 190 const Value* expected_; 191 }; 192 193 template <typename T> 194 class Impl<T, true> : public ::testing::MatcherInterface<T> { 195 public: 196 explicit Impl(const Value* expected) : expected_(expected) { 197 } 198 199 bool MatchAndExplain(T x, ::testing::MatchResultListener* listener) const override { 200 return expected_->Equals(x); 201 } 202 203 void DescribeTo(::std::ostream* os) const override { 204 *os << "is equal to " << *expected_; 205 } 206 207 void DescribeNegationTo(::std::ostream* os) const override { 208 *os << "is not equal to " << *expected_; 209 } 210 211 private: 212 DISALLOW_COPY_AND_ASSIGN(Impl); 213 214 const Value* expected_; 215 }; 216 217 ValueEq(const Value& expected) : expected_(&expected) { 218 } 219 ValueEq(const Value* expected) : expected_(expected) { 220 } 221 ValueEq(const ValueEq&) = default; 222 223 template <typename T> 224 operator ::testing::Matcher<T>() const { 225 return ::testing::Matcher<T>(new Impl<T, std::is_pointer<T>::value>(expected_)); 226 } 227 228 private: 229 const Value* expected_; 230 }; 231 232 // MATCHER_P(ValueEq, a, 233 // std::string(negation ? "isn't" : "is") + " equal to " + ::testing::PrintToString(a)) { 234 // return arg.Equals(&a); 235 //} 236 237 MATCHER_P(StrValueEq, a, 238 std::string(negation ? "isn't" : "is") + " equal to " + ::testing::PrintToString(a)) { 239 return *(arg.value) == a; 240 } 241 242 MATCHER_P(HasValue, name, 243 std::string(negation ? "does not have" : "has") + " value " + 244 ::testing::PrintToString(name)) { 245 return GetValueForConfig<Value>(&(*arg), name, {}) != nullptr; 246 } 247 248 MATCHER_P2(HasValue, name, config, 249 std::string(negation ? "does not have" : "has") + " value " + 250 ::testing::PrintToString(name) + " for config " + ::testing::PrintToString(config)) { 251 return GetValueForConfig<Value>(&(*arg), name, config) != nullptr; 252 } 253 254 } // namespace test 255 } // namespace aapt 256 257 #endif /* AAPT_TEST_COMMON_H */ 258