Home | History | Annotate | Download | only in shill
      1 //
      2 // Copyright (C) 2014 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 SHILL_TESTING_H_
     18 #define SHILL_TESTING_H_
     19 
     20 #include <gmock/gmock.h>
     21 #include <gtest/gtest.h>
     22 
     23 #include "shill/error.h"
     24 #include "shill/key_value_store.h"
     25 #include "shill/logging.h"
     26 
     27 namespace shill {
     28 
     29 // A Google Mock action (similar to testing::ReturnPointee) that takes a pointer
     30 // to a unique_ptr object, releases and returns the raw pointer managed by the
     31 // unique_ptr object when the action is invoked.
     32 //
     33 // Example usage:
     34 //
     35 //   TEST(FactoryTest, CreateStuff) {
     36 //     MockFactory factory;
     37 //     unique_ptr<Stuff> stuff(new Stuff());
     38 //     EXPECT_CALL(factory, CreateStuff())
     39 //         .WillOnce(ReturnAndReleasePointee(&stuff));
     40 //   }
     41 //
     42 // If |factory.CreateStuff()| is called, the ownership of the Stuff object
     43 // managed by |stuff| is transferred to the caller of |factory.CreateStuff()|.
     44 // Otherwise, the Stuff object will be destroyed once |stuff| goes out of
     45 // scope when the test completes.
     46 ACTION_P(ReturnAndReleasePointee, unique_pointer) {
     47   return unique_pointer->release();
     48 }
     49 
     50 MATCHER(IsSuccess, "") {
     51   return arg.IsSuccess();
     52 }
     53 
     54 MATCHER(IsFailure, "") {
     55   return arg.IsFailure();
     56 }
     57 
     58 MATCHER_P2(ErrorIs, error_type, error_message, "") {
     59   return error_type == arg.type() && error_message == arg.message();
     60 }
     61 
     62 MATCHER_P(ErrorTypeIs, error_type, "") {
     63   return error_type == arg.type();
     64 }
     65 
     66 MATCHER(IsNullRefPtr, "") {
     67   return !arg.get();
     68 }
     69 
     70 MATCHER(NotNullRefPtr, "") {
     71   return arg.get();
     72 }
     73 
     74 // Use this matcher instead of passing RefPtrs directly into the arguments
     75 // of EXPECT_CALL() because otherwise we may create un-cleaned-up references at
     76 // system teardown.
     77 MATCHER_P(IsRefPtrTo, ref_address, "") {
     78   return arg.get() == ref_address;
     79 }
     80 
     81 MATCHER_P(KeyValueStoreEq, value, "") {
     82   bool match = value.properties() == arg.properties();
     83   if (!match) {
     84     *result_listener << "\nExpected KeyValueStore:\n"
     85                      << "\tproperties: "
     86                      << testing::PrintToString(value.properties());
     87   }
     88   return match;
     89 }
     90 
     91 template<int error_argument_index>
     92 class SetErrorTypeInArgumentAction {
     93  public:
     94   SetErrorTypeInArgumentAction(Error::Type error_type, bool warn_default)
     95       : error_type_(error_type),
     96         warn_default_(warn_default) {}
     97 
     98   template <typename Result, typename ArgumentTuple>
     99   Result Perform(const ArgumentTuple& args) const {
    100     Error* error_arg = ::std::tr1::get<error_argument_index>(args);
    101     if (error_arg)
    102       error_arg->Populate(error_type_);
    103 
    104     // You should be careful if you see this warning in your log messages: it is
    105     // likely that you want to instead set a non-default expectation on this
    106     // mock, to test the success code-paths.
    107     if (warn_default_)
    108       LOG(WARNING) << "Default action taken: set error to "
    109                    << error_type_
    110                    << "(" << (error_arg ? error_arg->message() : "") << ")";
    111   }
    112 
    113  private:
    114   Error::Type error_type_;
    115   bool warn_default_;
    116 };
    117 
    118 // Many functions in the the DBus proxy classes take a (shill::Error*) output
    119 // argument that is set to shill::Error::kOperationFailed to notify the caller
    120 // synchronously of error conditions.
    121 //
    122 // If an error is not returned synchronously, a callback (passed as another
    123 // argument to the function) must eventually be called with the result/error.
    124 // Mock classes for these proxies should by default return failure synchronously
    125 // so that callers do not expect the callback to be called.
    126 template<int error_argument_index>
    127 ::testing::PolymorphicAction<SetErrorTypeInArgumentAction<error_argument_index>>
    128 SetOperationFailedInArgumentAndWarn() {
    129   return ::testing::MakePolymorphicAction(
    130       SetErrorTypeInArgumentAction<error_argument_index>(
    131           Error::kOperationFailed,
    132           true));
    133 }
    134 
    135 // Use this action to set the (shill::Error*) output argument to any
    136 // shill::Error value on mock DBus proxy method calls.
    137 template<int error_argument_index>
    138 ::testing::PolymorphicAction<SetErrorTypeInArgumentAction<error_argument_index>>
    139 SetErrorTypeInArgument(Error::Type error_type) {
    140   return ::testing::MakePolymorphicAction(
    141       SetErrorTypeInArgumentAction<error_argument_index>(error_type, false));
    142 }
    143 
    144 }  // namespace shill
    145 
    146 #endif  // SHILL_TESTING_H_
    147