Home | History | Annotate | Download | only in test
      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: " << str;
     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: " << str;
     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   std::unique_ptr<io::InputStream> OpenInputStream() override {
     94     return OpenAsData();
     95   }
     96 
     97   const Source& GetSource() const override {
     98     return source_;
     99   }
    100 
    101  private:
    102   DISALLOW_COPY_AND_ASSIGN(TestFile);
    103 
    104   Source source_;
    105 };
    106 
    107 }  // namespace test
    108 
    109 // Workaround gtest bug (https://github.com/google/googletest/issues/443)
    110 // that does not select base class operator<< for derived class T.
    111 template <typename T>
    112 typename std::enable_if<std::is_base_of<Value, T>::value, std::ostream&>::type operator<<(
    113     std::ostream& out, const T& value) {
    114   value.Print(&out);
    115   return out;
    116 }
    117 
    118 template std::ostream& operator<<<Item>(std::ostream&, const Item&);
    119 template std::ostream& operator<<<Reference>(std::ostream&, const Reference&);
    120 template std::ostream& operator<<<Id>(std::ostream&, const Id&);
    121 template std::ostream& operator<<<RawString>(std::ostream&, const RawString&);
    122 template std::ostream& operator<<<String>(std::ostream&, const String&);
    123 template std::ostream& operator<<<StyledString>(std::ostream&, const StyledString&);
    124 template std::ostream& operator<<<FileReference>(std::ostream&, const FileReference&);
    125 template std::ostream& operator<<<BinaryPrimitive>(std::ostream&, const BinaryPrimitive&);
    126 template std::ostream& operator<<<Attribute>(std::ostream&, const Attribute&);
    127 template std::ostream& operator<<<Style>(std::ostream&, const Style&);
    128 template std::ostream& operator<<<Array>(std::ostream&, const Array&);
    129 template std::ostream& operator<<<Plural>(std::ostream&, const Plural&);
    130 
    131 // Add a print method to Maybe.
    132 template <typename T>
    133 void PrintTo(const Maybe<T>& value, std::ostream* out) {
    134   if (value) {
    135     *out << ::testing::PrintToString(value.value());
    136   } else {
    137     *out << "Nothing";
    138   }
    139 }
    140 
    141 namespace test {
    142 
    143 MATCHER_P(StrEq, a,
    144           std::string(negation ? "isn't" : "is") + " equal to " +
    145               ::testing::PrintToString(android::StringPiece16(a))) {
    146   return android::StringPiece16(arg) == a;
    147 }
    148 
    149 template <typename T>
    150 class ValueEqImpl : public ::testing::MatcherInterface<T> {
    151  public:
    152   explicit ValueEqImpl(const Value* expected) : expected_(expected) {
    153   }
    154 
    155   bool MatchAndExplain(T x, ::testing::MatchResultListener* listener) const override {
    156     return expected_->Equals(&x);
    157   }
    158 
    159   void DescribeTo(::std::ostream* os) const override {
    160     *os << "is equal to " << *expected_;
    161   }
    162 
    163   void DescribeNegationTo(::std::ostream* os) const override {
    164     *os << "is not equal to " << *expected_;
    165   }
    166 
    167  private:
    168   DISALLOW_COPY_AND_ASSIGN(ValueEqImpl);
    169 
    170   const Value* expected_;
    171 };
    172 
    173 template <typename TValue>
    174 class ValueEqMatcher {
    175  public:
    176   ValueEqMatcher(TValue expected) : expected_(std::move(expected)) {
    177   }
    178 
    179   template <typename T>
    180   operator ::testing::Matcher<T>() const {
    181     return ::testing::Matcher<T>(new ValueEqImpl<T>(&expected_));
    182   }
    183 
    184  private:
    185   TValue expected_;
    186 };
    187 
    188 template <typename TValue>
    189 class ValueEqPointerMatcher {
    190  public:
    191   ValueEqPointerMatcher(const TValue* expected) : expected_(expected) {
    192   }
    193 
    194   template <typename T>
    195   operator ::testing::Matcher<T>() const {
    196     return ::testing::Matcher<T>(new ValueEqImpl<T>(expected_));
    197   }
    198 
    199  private:
    200   const TValue* expected_;
    201 };
    202 
    203 template <typename TValue,
    204           typename = typename std::enable_if<!std::is_pointer<TValue>::value, void>::type>
    205 inline ValueEqMatcher<TValue> ValueEq(TValue value) {
    206   return ValueEqMatcher<TValue>(std::move(value));
    207 }
    208 
    209 template <typename TValue>
    210 inline ValueEqPointerMatcher<TValue> ValueEq(const TValue* value) {
    211   return ValueEqPointerMatcher<TValue>(value);
    212 }
    213 
    214 MATCHER_P(StrValueEq, a,
    215           std::string(negation ? "isn't" : "is") + " equal to " + ::testing::PrintToString(a)) {
    216   return *(arg.value) == a;
    217 }
    218 
    219 MATCHER_P(HasValue, name,
    220           std::string(negation ? "does not have" : "has") + " value " +
    221               ::testing::PrintToString(name)) {
    222   return GetValueForConfig<Value>(&(*arg), name, {}) != nullptr;
    223 }
    224 
    225 MATCHER_P2(HasValue, name, config,
    226            std::string(negation ? "does not have" : "has") + " value " +
    227                ::testing::PrintToString(name) + " for config " + ::testing::PrintToString(config)) {
    228   return GetValueForConfig<Value>(&(*arg), name, config) != nullptr;
    229 }
    230 
    231 }  // namespace test
    232 }  // namespace aapt
    233 
    234 #endif /* AAPT_TEST_COMMON_H */
    235