1 // Copyright (C) 2023 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #pragma once 16 17 #include <gmock/gmock.h> 18 #include <gtest/gtest.h> 19 20 #include <ostream> 21 22 #include "frameworks/proto_logging/stats/atoms.pb.h" 23 #include "frameworks/proto_logging/stats/attribution_node.pb.h" 24 #include "packages/modules/StatsD/statsd/src/guardrail/stats_log_enums.pb.h" 25 #include "packages/modules/StatsD/statsd/src/shell/shell_data.pb.h" 26 #include "packages/modules/StatsD/statsd/src/stats_log.pb.h" 27 28 namespace android { 29 namespace os { 30 namespace statsd { 31 32 using PackageInfo = UidMapping_PackageInfoSnapshot_PackageInfo; 33 34 // clang-format off 35 36 #define PROPERTY_MATCHER(typename, propname, matcher) \ 37 testing::Property(#propname, &typename::propname, matcher(expected.propname())) 38 39 #define REPEATED_PROPERTY_MATCHER(typename, propname, matcher) \ 40 testing::Property(#propname, &typename::propname, \ 41 testing::Pointwise(matcher(), expected.propname())) 42 43 #define PROPERTY_EQ(typename, propname) PROPERTY_MATCHER(typename, propname, testing::Eq) 44 45 #define REPEATED_PROPERTY_EQ(typename, propname) \ 46 REPEATED_PROPERTY_MATCHER(typename, propname, testing::Eq) 47 48 /** 49 * Generate a GoogleTest equality matcher for a custom type specified by typename with the given 50 * properties. 51 * 52 * Example: For the protos: 53 * message Bar { 54 * optional int32 aa = 1; 55 * } 56 * message Foo { 57 * optional int32 a = 1; 58 * repeated float b = 2; 59 * optional Bar bar = 3; 60 * repeated Bar repeated_bar = 4; 61 * } 62 * This will generate equality matchers for them called EqBar() and EqFoo(): 63 * EQ_MATCHER(Bar, PROPERTY_EQ(Bar, aa)); 64 * EQ_MATCHER(Foo, 65 * PROPERTY_EQ(Foo, a), 66 * PROPERTY_EQ(Foo, b), 67 * PROPERTY_MATCHER(Foo, bar, EqBar), 68 * REPEATED_PROPERTY_MATCHER(Foo, repeated_bar, EqBar) 69 * ); 70 */ 71 #define EQ_MATCHER(typename, properties...) \ 72 MATCHER(Eq##typename, " ") { \ 73 return testing::Matches(Eq##typename(std::get<1>(arg)))(std::get<0>(arg)); \ 74 } \ 75 MATCHER_P(Eq##typename, expected, testing::PrintToString(expected)) { \ 76 return testing::ExplainMatchResult(testing::AllOf(properties), arg, result_listener); \ 77 } 78 79 #define PROPERTY_PRINT(propname) \ 80 if (obj.has_##propname()) { \ 81 *os << #propname << ": " << testing::PrintToString(obj.propname()) << ", "; \ 82 } 83 84 #define REPEATED_PROPERTY_PRINT(propname) \ 85 if (obj.propname##_size() > 0) { \ 86 *os << #propname << ": " << testing::PrintToString(obj.propname()) << ", "; \ 87 } 88 89 /** 90 * Generates a method that teaches GoogleTest how to print a custom type specified by typename 91 * with the given properties. 92 * The equality matcher generated by EQ_MATCHER for the given typename will use this generated 93 * printer method to print the object when the matcher fails. 94 * 95 * Example: For the protos: 96 * message Bar { 97 * optional int32 aa = 1; 98 * } 99 * message Foo { 100 * optional int32 a = 1; 101 * repeated float b = 2; 102 * optional Bar bar = 3; 103 * repeated Bar repeated_bar = 4; 104 * } 105 * This will generate printer methods for them: 106 * TYPE_PRINTER(Bar, PROPERTY_PRINT(aa)); 107 * TYPE_PRINTER(Foo, 108 * PROPERTY_PRINT(a) 109 * PROPERTY_PRINT(b) 110 * PROPERTY_PRINT(bar) 111 * REPEATED_PROPERTY_PRINT(repeated_bar) 112 * ); 113 */ 114 #define TYPE_PRINTER(typename, properties) \ 115 inline void PrintTo(const typename& obj, std::ostream* os) { \ 116 *os << #typename << ": { "; \ 117 properties \ 118 *os << "}"; \ 119 } 120 121 EQ_MATCHER(PackageInfo, 122 PROPERTY_EQ(PackageInfo, version), 123 PROPERTY_EQ(PackageInfo, uid), 124 PROPERTY_EQ(PackageInfo, deleted), 125 PROPERTY_EQ(PackageInfo, truncated_certificate_hash), 126 PROPERTY_EQ(PackageInfo, name_hash), 127 PROPERTY_EQ(PackageInfo, version_string_hash), 128 PROPERTY_EQ(PackageInfo, name), 129 PROPERTY_EQ(PackageInfo, version_string), 130 PROPERTY_EQ(PackageInfo, installer_index), 131 PROPERTY_EQ(PackageInfo, installer_hash), 132 PROPERTY_EQ(PackageInfo, installer) 133 ); 134 TYPE_PRINTER(PackageInfo, 135 PROPERTY_PRINT(version) 136 PROPERTY_PRINT(uid) 137 PROPERTY_PRINT(deleted) 138 PROPERTY_PRINT(truncated_certificate_hash) 139 PROPERTY_PRINT(name_hash) 140 PROPERTY_PRINT(version_string_hash) 141 PROPERTY_PRINT(name) 142 PROPERTY_PRINT(version_string) 143 PROPERTY_PRINT(installer_index) 144 PROPERTY_PRINT(installer_hash) 145 PROPERTY_PRINT(installer) 146 ); 147 148 EQ_MATCHER(AttributionNode, 149 PROPERTY_EQ(AttributionNode, uid), 150 PROPERTY_EQ(AttributionNode, tag) 151 ); 152 TYPE_PRINTER(AttributionNode, 153 PROPERTY_PRINT(uid) 154 PROPERTY_PRINT(tag) 155 ); 156 157 EQ_MATCHER(ScreenStateChanged, PROPERTY_EQ(ScreenStateChanged, state)); 158 TYPE_PRINTER(ScreenStateChanged, PROPERTY_PRINT(state)); 159 160 EQ_MATCHER(TrainExperimentIds, 161 REPEATED_PROPERTY_EQ(TrainExperimentIds, experiment_id) 162 ); 163 TYPE_PRINTER(TrainExperimentIds, REPEATED_PROPERTY_PRINT(experiment_id)); 164 165 EQ_MATCHER(TestAtomReported, 166 REPEATED_PROPERTY_MATCHER(TestAtomReported, attribution_node, EqAttributionNode), 167 PROPERTY_EQ(TestAtomReported, int_field), 168 PROPERTY_EQ(TestAtomReported, long_field), 169 PROPERTY_EQ(TestAtomReported, float_field), 170 PROPERTY_EQ(TestAtomReported, string_field), 171 PROPERTY_EQ(TestAtomReported, boolean_field), 172 PROPERTY_EQ(TestAtomReported, state), 173 PROPERTY_MATCHER(TestAtomReported, bytes_field, EqTrainExperimentIds), 174 REPEATED_PROPERTY_EQ(TestAtomReported, repeated_int_field), 175 REPEATED_PROPERTY_EQ(TestAtomReported, repeated_long_field), 176 REPEATED_PROPERTY_EQ(TestAtomReported, repeated_float_field), 177 REPEATED_PROPERTY_EQ(TestAtomReported, repeated_string_field), 178 REPEATED_PROPERTY_EQ(TestAtomReported, repeated_boolean_field), 179 REPEATED_PROPERTY_EQ(TestAtomReported, repeated_enum_field) 180 ); 181 TYPE_PRINTER(TestAtomReported, 182 REPEATED_PROPERTY_PRINT(attribution_node) 183 PROPERTY_PRINT(int_field) 184 PROPERTY_PRINT(long_field) 185 PROPERTY_PRINT(float_field) 186 PROPERTY_PRINT(string_field) 187 PROPERTY_PRINT(boolean_field) 188 PROPERTY_PRINT(state) 189 PROPERTY_PRINT(bytes_field) 190 REPEATED_PROPERTY_PRINT(repeated_int_field) 191 REPEATED_PROPERTY_PRINT(repeated_long_field) 192 REPEATED_PROPERTY_PRINT(repeated_float_field) 193 REPEATED_PROPERTY_PRINT(repeated_string_field) 194 REPEATED_PROPERTY_PRINT(repeated_boolean_field) 195 REPEATED_PROPERTY_PRINT(repeated_enum_field) 196 ); 197 198 EQ_MATCHER(CpuActiveTime, 199 PROPERTY_EQ(CpuActiveTime, uid), 200 PROPERTY_EQ(CpuActiveTime, time_millis) 201 ); 202 TYPE_PRINTER(CpuActiveTime, 203 PROPERTY_PRINT(uid) 204 PROPERTY_PRINT(time_millis) 205 ); 206 207 EQ_MATCHER(PluggedStateChanged, PROPERTY_EQ(PluggedStateChanged, state)); 208 TYPE_PRINTER(PluggedStateChanged, PROPERTY_PRINT(state)); 209 210 EQ_MATCHER(WakelockStateChanged, 211 REPEATED_PROPERTY_MATCHER(WakelockStateChanged, attribution_node, EqAttributionNode), 212 PROPERTY_EQ(WakelockStateChanged, type), 213 PROPERTY_EQ(WakelockStateChanged, tag), 214 PROPERTY_EQ(WakelockStateChanged, state), 215 PROPERTY_EQ(WakelockStateChanged, process_state) 216 ); 217 TYPE_PRINTER(WakelockStateChanged, 218 REPEATED_PROPERTY_PRINT(attribution_node) 219 PROPERTY_PRINT(type) 220 PROPERTY_PRINT(tag) 221 PROPERTY_PRINT(state) 222 PROPERTY_PRINT(process_state) 223 ); 224 225 EQ_MATCHER(Atom, 226 PROPERTY_MATCHER(Atom, screen_state_changed, EqScreenStateChanged), 227 PROPERTY_MATCHER(Atom, test_atom_reported, EqTestAtomReported), 228 PROPERTY_MATCHER(Atom, wakelock_state_changed, EqWakelockStateChanged) 229 ); 230 TYPE_PRINTER(Atom, 231 PROPERTY_PRINT(screen_state_changed) 232 PROPERTY_PRINT(test_atom_reported) 233 PROPERTY_PRINT(wakelock_state_changed) 234 ); 235 236 EQ_MATCHER(ShellData, 237 REPEATED_PROPERTY_MATCHER(ShellData, atom, EqAtom), 238 REPEATED_PROPERTY_EQ(ShellData, elapsed_timestamp_nanos), 239 REPEATED_PROPERTY_EQ(ShellData, logging_uid) 240 ); 241 TYPE_PRINTER(ShellData, 242 REPEATED_PROPERTY_PRINT(atom) 243 REPEATED_PROPERTY_PRINT(elapsed_timestamp_nanos) 244 REPEATED_PROPERTY_PRINT(logging_uid) 245 ); 246 247 using CounterStats = StatsdStatsReport_CounterStats; 248 249 EQ_MATCHER(CounterStats, 250 PROPERTY_EQ(CounterStats, counter_type), 251 PROPERTY_EQ(CounterStats, count) 252 ); 253 TYPE_PRINTER(CounterStats, 254 PROPERTY_PRINT(counter_type) 255 PROPERTY_PRINT(count) 256 ); 257 258 using AtomStats = StatsdStatsReport_AtomStats; 259 260 EQ_MATCHER(AtomStats, 261 PROPERTY_EQ(AtomStats, tag), 262 PROPERTY_EQ(AtomStats, count), 263 PROPERTY_EQ(AtomStats, error_count), 264 PROPERTY_EQ(AtomStats, dropped_count), 265 PROPERTY_EQ(AtomStats, skip_count), 266 PROPERTY_EQ(AtomStats, peak_rate) 267 ); 268 TYPE_PRINTER(AtomStats, 269 PROPERTY_PRINT(tag) 270 PROPERTY_PRINT(count) 271 PROPERTY_PRINT(error_count) 272 PROPERTY_PRINT(dropped_count) 273 PROPERTY_PRINT(skip_count) 274 PROPERTY_PRINT(peak_rate) 275 ); 276 277 // clang-format on 278 279 } // namespace statsd 280 } // namespace os 281 } // namespace android 282