1 // Copyright 2018 The Chromium 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 CHROME_BROWSER_UI_APP_LIST_SEARCH_SEARCH_RESULT_RANKER_APP_LAUNCH_PREDICTOR_TEST_UTIL_H_
6 #define CHROME_BROWSER_UI_APP_LIST_SEARCH_SEARCH_RESULT_RANKER_APP_LAUNCH_PREDICTOR_TEST_UTIL_H_
7
8 #include <string>
9
10 #include "chrome/browser/ui/app_list/search/search_result_ranker/app_launch_predictor.pb.h"
11 #include "chrome/browser/ui/app_list/search/search_result_ranker/frecency_store.pb.h"
12 #include "chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.pb.h"
13 #include "chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker.pb.h"
14 #include "third_party/protobuf/src/google/protobuf/stubs/mathutil.h"
15
16 namespace app_list {
17
18 // Returns whether two protos are equivalent, which is defined as:
19 // (1) each integer field has the same value.
20 // (2) each float field has to be AlmostEqual.
21 // (3) each map field should have same pairs of key-value.
22 // (4) each repeated field should have the same values, in the same order.
23 // (5) each proto field is defined recursively.
24 // Note:
25 // (1) This function should only be used for MessageLite where reflection is
26 // not supported; otherwise MessageDifferencer is preferred.
27 // (2) This function will not support any proto by default; new proto (and all
28 // its sub-proto) should be added with macro DEFINE_EQUIVTO_PROTO_LITE_*.
29 template <typename Proto>
30 bool EquivToProtoLite(const Proto& p1, const Proto& p2);
31
32 namespace internal {
33
34 // General templated class for implementation of EquivToProtoLite;
35 template <typename Proto>
36 class EquivToProtoLiteImpl {};
37
38 // Specialized by std::string.
39 template <>
40 class EquivToProtoLiteImpl<std::string> {
41 public:
operator()42 bool operator()(const std::string& p1, const std::string& p2) {
43 return p1 == p2;
44 }
45 };
46
47 // Specialized by int32_t.
48 template <>
49 class EquivToProtoLiteImpl<int32_t> {
50 public:
operator()51 bool operator()(const int32_t p1, const int32_t p2) { return p1 == p2; }
52 };
53
54 // Specialized by unsigned int.
55 template <>
56 class EquivToProtoLiteImpl<unsigned int> {
57 public:
operator()58 bool operator()(const unsigned int p1, const unsigned int p2) {
59 return p1 == p2;
60 }
61 };
62
63 // Specialized by float.
64 template <>
65 class EquivToProtoLiteImpl<float> {
66 public:
operator()67 bool operator()(const float p1, const float p2) {
68 return google::protobuf::MathUtil::AlmostEquals(p1, p2);
69 }
70 };
71
72 // Specialized by unsigned long.
73 template <>
74 class EquivToProtoLiteImpl<unsigned long> {
75 public:
operator()76 bool operator()(const unsigned long p1, const unsigned long p2) {
77 return p1 == p2;
78 }
79 };
80
81 // Specialized by unsigned long long.
82 template <>
83 class EquivToProtoLiteImpl<unsigned long long> {
84 public:
operator()85 bool operator()(const unsigned long long p1, const unsigned long long p2) {
86 return p1 == p2;
87 }
88 };
89
90 // Specialized by google::protobuf::Map.
91 template <typename K, typename V>
92 class EquivToProtoLiteImpl<google::protobuf::Map<K, V>> {
93 public:
94 using Map = google::protobuf::Map<K, V>;
operator()95 bool operator()(const Map& p1, const Map& p2) {
96 if (p1.size() != p2.size())
97 return false;
98 for (const auto& pair : p1) {
99 const auto find_in_p2 = p2.find(pair.first);
100 if (find_in_p2 == p2.end())
101 return false;
102 if (!EquivToProtoLite(pair.second, find_in_p2->second))
103 return false;
104 }
105
106 return true;
107 }
108 };
109
110 // Specialized by RepeatedPtrField.
111 template <typename T>
112 class EquivToProtoLiteImpl<google::protobuf::RepeatedPtrField<T>> {
113 public:
114 using Repeated = google::protobuf::RepeatedPtrField<T>;
operator()115 bool operator()(const Repeated& p1, const Repeated& p2) {
116 if (p1.size() != p2.size())
117 return false;
118
119 for (int i = 0; i < p1.size(); ++i) {
120 const auto& v1 = p1.Get(i);
121 const auto& v2 = p2.Get(i);
122
123 if (!EquivToProtoLite(v1, v2))
124 return false;
125 }
126
127 return true;
128 }
129 };
130
131 #define DEFINE_EQUIVTO_PROTO_LITE_DEFAULT(Proto) \
132 template <> \
133 class EquivToProtoLiteImpl<Proto> { \
134 public: \
135 bool operator()(const Proto& t1, const Proto& t2) { \
136 return t1.SerializeAsString() == t2.SerializeAsString(); \
137 } \
138 }
139
140 #define DEFINE_EQUIVTO_PROTO_LITE_1(Proto, f1) \
141 template <> \
142 class EquivToProtoLiteImpl<Proto> { \
143 public: \
144 bool operator()(const Proto& t1, const Proto& t2) { \
145 return EquivToProtoLite(t1.f1(), t2.f1()); \
146 } \
147 }
148
149 #define DEFINE_EQUIVTO_PROTO_LITE_2(Proto, f1, f2) \
150 template <> \
151 class EquivToProtoLiteImpl<Proto> { \
152 public: \
153 bool operator()(const Proto& t1, const Proto& t2) { \
154 return EquivToProtoLite(t1.f1(), t2.f1()) && \
155 EquivToProtoLite(t1.f2(), t2.f2()); \
156 } \
157 }
158
159 #define DEFINE_EQUIVTO_PROTO_LITE_3(Proto, f1, f2, f3) \
160 template <> \
161 class EquivToProtoLiteImpl<Proto> { \
162 public: \
163 bool operator()(const Proto& t1, const Proto& t2) { \
164 return EquivToProtoLite(t1.f1(), t2.f1()) && \
165 EquivToProtoLite(t1.f2(), t2.f2()) && \
166 EquivToProtoLite(t1.f3(), t2.f3()); \
167 } \
168 }
169
170 #define DEFINE_EQUIVTO_PROTO_LITE_4(Proto, f1, f2, f3, f4) \
171 template <> \
172 class EquivToProtoLiteImpl<Proto> { \
173 public: \
174 bool operator()(const Proto& t1, const Proto& t2) { \
175 return EquivToProtoLite(t1.f1(), t2.f1()) && \
176 EquivToProtoLite(t1.f2(), t2.f2()) && \
177 EquivToProtoLite(t1.f3(), t2.f3()) && \
178 EquivToProtoLite(t1.f4(), t2.f4()); \
179 } \
180 }
181
182 #define DEFINE_EQUIVTO_PROTO_LITE_5(Proto, f1, f2, f3, f4, f5) \
183 template <> \
184 class EquivToProtoLiteImpl<Proto> { \
185 public: \
186 bool operator()(const Proto& t1, const Proto& t2) { \
187 return EquivToProtoLite(t1.f1(), t2.f1()) && \
188 EquivToProtoLite(t1.f2(), t2.f2()) && \
189 EquivToProtoLite(t1.f3(), t2.f3()) && \
190 EquivToProtoLite(t1.f4(), t2.f4()) && \
191 EquivToProtoLite(t1.f5(), t2.f5()); \
192 } \
193 }
194
195 // Macro that generates a specialization for |Proto| with four fields.
196 #define DEFINE_EQUIVTO_PROTO_LITE_6(Proto, f1, f2, f3, f4, f5, f6) \
197 template <> \
198 class EquivToProtoLiteImpl<Proto> { \
199 public: \
200 bool operator()(const Proto& t1, const Proto& t2) { \
201 return EquivToProtoLite(t1.f1(), t2.f1()) && \
202 EquivToProtoLite(t1.f2(), t2.f2()) && \
203 EquivToProtoLite(t1.f3(), t2.f3()) && \
204 EquivToProtoLite(t1.f4(), t2.f4()) && \
205 EquivToProtoLite(t1.f5(), t2.f5()) && \
206 EquivToProtoLite(t1.f6(), t2.f6()); \
207 } \
208 }
209
210 DEFINE_EQUIVTO_PROTO_LITE_3(AppLaunchPredictorProto,
211 fake_app_launch_predictor,
212 hour_app_launch_predictor,
213 serialized_mrfu_app_launch_predictor);
214
215 DEFINE_EQUIVTO_PROTO_LITE_1(FakeAppLaunchPredictorProto, rank_result);
216
217 DEFINE_EQUIVTO_PROTO_LITE_1(FakePredictorProto, counts);
218
219 DEFINE_EQUIVTO_PROTO_LITE_5(FrecencyStoreProto,
220 values,
221 value_limit,
222 decay_coeff,
223 num_updates,
224 next_id);
225
226 DEFINE_EQUIVTO_PROTO_LITE_3(FrecencyStoreProto_ValueData,
227 id,
228 last_score,
229 last_num_updates);
230
231 DEFINE_EQUIVTO_PROTO_LITE_1(HourBinPredictorProto, binned_frequency_table);
232
233 DEFINE_EQUIVTO_PROTO_LITE_2(HourBinPredictorProto_FrequencyTable,
234 total_counts,
235 frequency);
236
237 DEFINE_EQUIVTO_PROTO_LITE_1(HourAppLaunchPredictorProto,
238 binned_frequency_table);
239
240 DEFINE_EQUIVTO_PROTO_LITE_2(HourAppLaunchPredictorProto_FrequencyTable,
241 total_counts,
242 frequency);
243
244 DEFINE_EQUIVTO_PROTO_LITE_2(RecurrencePredictorProto,
245 fake_predictor,
246 frecency_predictor);
247
248 DEFINE_EQUIVTO_PROTO_LITE_2(RecurrenceRankerProto, config_hash, predictor);
249
250 DEFINE_EQUIVTO_PROTO_LITE_2(SerializedMrfuAppLaunchPredictorProto,
251 num_of_trains,
252 scores);
253
254 DEFINE_EQUIVTO_PROTO_LITE_2(SerializedMrfuAppLaunchPredictorProto_Score,
255 num_of_trains_at_last_update,
256 last_score);
257
258 DEFINE_EQUIVTO_PROTO_LITE_2(FrecencyPredictorProto, targets, num_updates);
259
260 DEFINE_EQUIVTO_PROTO_LITE_2(FrecencyPredictorProto_TargetData,
261 last_score,
262 last_num_updates);
263
264 } // namespace internal
265
266 template <typename Proto>
EquivToProtoLite(const Proto & p1,const Proto & p2)267 bool EquivToProtoLite(const Proto& p1, const Proto& p2) {
268 return internal::EquivToProtoLiteImpl<Proto>()(p1, p2);
269 }
270
271 } // namespace app_list
272
273 #endif // CHROME_BROWSER_UI_APP_LIST_SEARCH_SEARCH_RESULT_RANKER_APP_LAUNCH_PREDICTOR_TEST_UTIL_H_
274