blob: 10769deb00e4dcdaf4a92429e53cff4a38f184a2 [file] [log] [blame]
Gary Morainbaeefdf2012-04-30 14:53:35 -07001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef SHILL_KEY_VALUE_STORE_MATCHER_
6#define SHILL_KEY_VALUE_STORE_MATCHER_
7
8#include <gmock/gmock.h>
9#include "shill/key_value_store.h"
10
11// A GMock matcher for a shill::KeyValueStore. To be used in unittests.
12//
13// Usage:
14// KeyValueStore expected;
15// expected.SetBool(flimflam::kSIMLockEnabledProperty, false);
16// EXPECT_CALL(*device_adaptor_, EmitKeyValueStoreChanged(
17// flimflam::kSIMLockStatusProperty,
18// KeyValueStoreEq(expected)));
19//
20// The EXPECT_CALL will match if |expected| has the same contents as the actual
21// parameter passed to EmitKeyValueStoreChanged(). If the match fails, a helped
22// message is emitted to show the mismatch between the actual and expected
23// parameters, like this:
24//
25// Expected arg #1: KeyValueStore
26// bools-map equals { ("LockEnabled", false) } and
27// int-map equals {} and
28// string-map equals {} and
29// uint-map equals {}
30// Actual: 96-byte object <C607 51F6 0000 0000 089C F0F8 089C F0F8
31// 089C F0F8 0100 0000 14A3 3FF7 0000 0000 0000 0000 585C E5FF 585C
32// E5FF 0000 0000 0000 0000 0000 0000 489C F0F8 489C F0F8 489C F0F8
33// 0100 0000 AB5C E5FF 0000 0000 889C F0F8 889C F0F8 889C F0F8 0100
34// 0000> (
35// Unmatched bools: Only in actual: ("LockEnabled", true); not in actual:
36// ("LockEnabled", false)
37// Unmatched ints:
38// Unmatched strings: Only in actual: ("LockType", "")
39// Unmatched uints: Only in actual: ("RetriesLeft", 0))
40// Expected: to be called once
41// Actual: never called - unsatisfied and active
42//
43// This shows you the expected value of the KeyValueStore, raw actual
44// KeyValueStore (which you can ignore), and, most importantly, the difference
45// between the actual and expected values.
46
47namespace shill {
48
49// This class is implemented instead of a simpler MATCHER_P so that the error
50// messages are clearer when a match fails. A KeyValueStore is a aggregate of
51// maps. This matcher uses ContainerEq to compare the maps of the expected
52// value to the actual one. It also uses the the DescribeTo() and
53// ExplainMatchResultsTo() methods of ContainerEq to print a useful message when
54// the actual and expected values differ. To do this, it needs a ContainerEq
55// object for each map contained by a KeyValueStore.
56class KeyValueStoreEqMatcher :
57 public testing::MatcherInterface<const KeyValueStore &> {
58 public:
59 explicit KeyValueStoreEqMatcher(const KeyValueStore &expected)
60 : expected_(expected),
61 bool_matcher_(testing::ContainerEq(expected_.bool_properties()).impl()),
62 int_matcher_(testing::ContainerEq(expected_.int_properties()).impl()),
63 string_matcher_(testing::ContainerEq(expected_.string_properties())
64 .impl()),
65 uint_matcher_(testing::ContainerEq(expected_.uint_properties()).impl())
66 {}
67 // Returns true iff the matcher matches |actual|. Each map of the actual
68 // KeyValueStore is compared to the maps contained with the |expected_|
69 // KeyValueStore. The comparison is done by the ContainerEq objects creating
70 // in the constructor.
71 virtual bool Matches(const KeyValueStore &actual) const {
72 return bool_matcher_.impl().Matches(actual.bool_properties()) &&
73 int_matcher_.impl().Matches(actual.int_properties()) &&
74 string_matcher_.impl().Matches(actual.string_properties()) &&
75 uint_matcher_.impl().Matches(actual.uint_properties());
76 }
77 // Describes this matcher to an ostream.
78 virtual void DescribeTo(::std::ostream* os) const {
79 *os << "KeyValueStore" << std::endl << "\tbools-map ";
80 bool_matcher_.impl().DescribeTo(os);
81 *os << " and" << std::endl << "\tint-map ";
82 int_matcher_.impl().DescribeTo(os);
83 *os << " and" << std::endl << "\tstring-map ";
84 string_matcher_.impl().DescribeTo(os);
85 *os << " and" << std::endl << "\tuint-map ";
86 uint_matcher_.impl().DescribeTo(os);
87 }
88
89 // Explains why a match failed.
90 virtual void ExplainMatchResultTo(const KeyValueStore &actual,
91 ::std::ostream* os) const {
92 *os << std::endl << "\tUnmatched bools: ";
93 bool_matcher_.impl().ExplainMatchResultTo(actual.bool_properties(), os);
94 *os << std::endl << "\tUnmatched ints: ";
95 int_matcher_.impl().ExplainMatchResultTo(actual.int_properties(), os);
96 *os << std::endl << "\tUnmatched strings: ";
97 string_matcher_.impl().ExplainMatchResultTo(actual.string_properties(), os);
98 *os << std::endl << "\tUnmatched uints: ";
99 uint_matcher_.impl().ExplainMatchResultTo(actual.uint_properties(), os);
100 }
101
102 private:
103 // The expected value. If |actual| passed to Matches does not equal this
104 // value, the match fails.
105 const KeyValueStore expected_;
106
107 // These are the ContainerEq objects used in the matching. This signature is
108 // lifted from gmock/gmock-matchers.h. One of these matchers is required for
109 // each map contained within a KeyValueStore.
110 testing::PolymorphicMatcher<
111 testing::internal::ContainerEqMatcher<std::map<std::string, bool> > >
112 bool_matcher_;
113
114 testing::PolymorphicMatcher<
115 testing::internal::ContainerEqMatcher<std::map<std::string, int> > >
116 int_matcher_;
117
118 testing::PolymorphicMatcher<
119 testing::internal::ContainerEqMatcher<std::map<std::string, std::string> > >
120 string_matcher_;
121
122 testing::PolymorphicMatcher<
123 testing::internal::ContainerEqMatcher<std::map<std::string, uint> > >
124 uint_matcher_;
125};
126
127inline testing::Matcher<const KeyValueStore&> KeyValueStoreEq(
128 const KeyValueStore &expected) {
129 return testing::MakeMatcher(new KeyValueStoreEqMatcher(expected));
130}
131
132} // namespace shill
133#endif // SHILL_KEY_VALUE_STORE_MATCHER_