Common.h revision e38567480be67ac83a8f8f090704bb0d49e2eed2
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 37namespace aapt { 38namespace test { 39 40IDiagnostics* GetDiagnostics(); 41 42inline ResourceName ParseNameOrDie(const android::StringPiece& str) { 43 ResourceNameRef ref; 44 CHECK(ResourceUtils::ParseResourceName(str, &ref)) << "invalid resource name"; 45 return ref.ToResourceName(); 46} 47 48inline ConfigDescription ParseConfigOrDie(const android::StringPiece& str) { 49 ConfigDescription config; 50 CHECK(ConfigDescription::Parse(str, &config)) << "invalid configuration"; 51 return config; 52} 53 54template <typename T = Value> 55T* 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 68template <> 69Value* GetValueForConfigAndProduct<Value>(ResourceTable* table, 70 const android::StringPiece& res_name, 71 const ConfigDescription& config, 72 const android::StringPiece& product); 73 74template <typename T = Value> 75T* GetValueForConfig(ResourceTable* table, const android::StringPiece& res_name, 76 const ConfigDescription& config) { 77 return GetValueForConfigAndProduct<T>(table, res_name, config, {}); 78} 79 80template <typename T = Value> 81T* GetValue(ResourceTable* table, const android::StringPiece& res_name) { 82 return GetValueForConfig<T>(table, res_name, {}); 83} 84 85class 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. 107template <typename T> 108typename 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 114template std::ostream& operator<<<Item>(std::ostream&, const Item&); 115template std::ostream& operator<<<Reference>(std::ostream&, const Reference&); 116template std::ostream& operator<<<Id>(std::ostream&, const Id&); 117template std::ostream& operator<<<RawString>(std::ostream&, const RawString&); 118template std::ostream& operator<<<String>(std::ostream&, const String&); 119template std::ostream& operator<<<StyledString>(std::ostream&, const StyledString&); 120template std::ostream& operator<<<FileReference>(std::ostream&, const FileReference&); 121template std::ostream& operator<<<BinaryPrimitive>(std::ostream&, const BinaryPrimitive&); 122template std::ostream& operator<<<Attribute>(std::ostream&, const Attribute&); 123template std::ostream& operator<<<Style>(std::ostream&, const Style&); 124template std::ostream& operator<<<Array>(std::ostream&, const Array&); 125template std::ostream& operator<<<Plural>(std::ostream&, const Plural&); 126 127// Add a print method to Maybe. 128template <typename T> 129void 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 137namespace test { 138 139MATCHER_P(ValueEq, a, 140 std::string(negation ? "isn't" : "is") + " equal to " + ::testing::PrintToString(a)) { 141 return arg.Equals(&a); 142} 143 144MATCHER_P(StrValueEq, a, 145 std::string(negation ? "isn't" : "is") + " equal to " + ::testing::PrintToString(a)) { 146 return *(arg.value) == a; 147} 148 149MATCHER_P(HasValue, name, 150 std::string(negation ? "does not have" : "has") + " value " + 151 ::testing::PrintToString(name)) { 152 return GetValueForConfig<Value>(&(*arg), name, {}) != nullptr; 153} 154 155MATCHER_P2(HasValue, name, config, 156 std::string(negation ? "does not have" : "has") + " value " + 157 ::testing::PrintToString(name) + " for config " + ::testing::PrintToString(config)) { 158 return GetValueForConfig<Value>(&(*arg), name, config) != nullptr; 159} 160 161} // namespace test 162} // namespace aapt 163 164#endif /* AAPT_TEST_COMMON_H */ 165