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";
     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