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/ConfigDescription.h"
     25 #include "androidfw/StringPiece.h"
     26 #include "gmock/gmock.h"
     27 #include "gtest/gtest.h"
     28 
     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 android::ConfigDescription ParseConfigOrDie(const android::StringPiece& str) {
     49     android::ConfigDescription config;
     50   CHECK(android::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 android::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 android::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 android::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   // NOLINTNEXTLINE(google-explicit-constructor)
    177   ValueEqMatcher(TValue expected) : expected_(std::move(expected)) {
    178   }
    179 
    180   template <typename T>
    181   // NOLINTNEXTLINE(google-explicit-constructor)
    182   operator ::testing::Matcher<T>() const {
    183     return ::testing::Matcher<T>(new ValueEqImpl<T>(&expected_));
    184   }
    185 
    186  private:
    187   TValue expected_;
    188 };
    189 
    190 template <typename TValue>
    191 class ValueEqPointerMatcher {
    192  public:
    193   // NOLINTNEXTLINE(google-explicit-constructor)
    194   ValueEqPointerMatcher(const TValue* expected) : expected_(expected) {
    195   }
    196 
    197   template <typename T>
    198   // NOLINTNEXTLINE(google-explicit-constructor)
    199   operator ::testing::Matcher<T>() const {
    200     return ::testing::Matcher<T>(new ValueEqImpl<T>(expected_));
    201   }
    202 
    203  private:
    204   const TValue* expected_;
    205 };
    206 
    207 template <typename TValue,
    208           typename = typename std::enable_if<!std::is_pointer<TValue>::value, void>::type>
    209 inline ValueEqMatcher<TValue> ValueEq(TValue value) {
    210   return ValueEqMatcher<TValue>(std::move(value));
    211 }
    212 
    213 template <typename TValue>
    214 inline ValueEqPointerMatcher<TValue> ValueEq(const TValue* value) {
    215   return ValueEqPointerMatcher<TValue>(value);
    216 }
    217 
    218 MATCHER_P(StrValueEq, a,
    219           std::string(negation ? "isn't" : "is") + " equal to " + ::testing::PrintToString(a)) {
    220   return *(arg.value) == a;
    221 }
    222 
    223 MATCHER_P(HasValue, name,
    224           std::string(negation ? "does not have" : "has") + " value " +
    225               ::testing::PrintToString(name)) {
    226   return GetValueForConfig<Value>(&(*arg), name, {}) != nullptr;
    227 }
    228 
    229 MATCHER_P2(HasValue, name, config,
    230            std::string(negation ? "does not have" : "has") + " value " +
    231                ::testing::PrintToString(name) + " for config " + ::testing::PrintToString(config)) {
    232   return GetValueForConfig<Value>(&(*arg), name, config) != nullptr;
    233 }
    234 
    235 }  // namespace test
    236 }  // namespace aapt
    237 
    238 #endif /* AAPT_TEST_COMMON_H */
    239