• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
ACTION_P(ReturnAndReleasePointee,unique_pointer)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:
SetErrorTypeInArgumentAction(Error::Type error_type,bool warn_default)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>
Perform(const ArgumentTuple & args)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>>
SetOperationFailedInArgumentAndWarn()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>>
SetErrorTypeInArgument(Error::Type error_type)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