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
27namespace 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.
46ACTION_P(ReturnAndReleasePointee, unique_pointer) {
47  return unique_pointer->release();
48}
49
50MATCHER(IsSuccess, "") {
51  return arg.IsSuccess();
52}
53
54MATCHER(IsFailure, "") {
55  return arg.IsFailure();
56}
57
58MATCHER_P2(ErrorIs, error_type, error_message, "") {
59  return error_type == arg.type() && error_message == arg.message();
60}
61
62MATCHER_P(ErrorTypeIs, error_type, "") {
63  return error_type == arg.type();
64}
65
66MATCHER(IsNullRefPtr, "") {
67  return !arg.get();
68}
69
70MATCHER(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.
77MATCHER_P(IsRefPtrTo, ref_address, "") {
78  return arg.get() == ref_address;
79}
80
81MATCHER_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
91template<int error_argument_index>
92class 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.
126template<int error_argument_index>
127::testing::PolymorphicAction<SetErrorTypeInArgumentAction<error_argument_index>>
128SetOperationFailedInArgumentAndWarn() {
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.
137template<int error_argument_index>
138::testing::PolymorphicAction<SetErrorTypeInArgumentAction<error_argument_index>>
139SetErrorTypeInArgument(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