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/shell/shell_data.pb.h" 25 #include "packages/modules/StatsD/statsd/src/stats_log.pb.h" 26 27 namespace android { 28 namespace os { 29 namespace statsd { 30 31 using PackageInfo = UidMapping_PackageInfoSnapshot_PackageInfo; 32 33 // clang-format off 34 35 #define PROPERTY_MATCHER(typename, propname, matcher) \ 36 testing::Property(#propname, &typename::propname, matcher(expected.propname())) 37 38 #define REPEATED_PROPERTY_MATCHER(typename, propname, matcher) \ 39 testing::Property(#propname, &typename::propname, \ 40 testing::Pointwise(matcher(), expected.propname())) 41 42 #define PROPERTY_EQ(typename, propname) PROPERTY_MATCHER(typename, propname, testing::Eq) 43 44 #define REPEATED_PROPERTY_EQ(typename, propname) \ 45 REPEATED_PROPERTY_MATCHER(typename, propname, testing::Eq) 46 47 /** 48 * Generate a GoogleTest equality matcher for a custom type specified by typename with the given 49 * properties. 50 * 51 * Example: For the protos: 52 * message Bar { 53 * optional int32 aa = 1; 54 * } 55 * message Foo { 56 * optional int32 a = 1; 57 * repeated float b = 2; 58 * optional Bar bar = 3; 59 * repeated Bar repeated_bar = 4; 60 * } 61 * This will generate equality matchers for them called EqBar() and EqFoo(): 62 * EQ_MATCHER(Bar, PROPERTY_EQ(Bar, aa)); 63 * EQ_MATCHER(Foo, 64 * PROPERTY_EQ(Foo, a), 65 * PROPERTY_EQ(Foo, b), 66 * PROPERTY_MATCHER(Foo, bar, EqBar), 67 * REPEATED_PROPERTY_MATCHER(Foo, repeated_bar, EqBar) 68 * ); 69 */ 70 #define EQ_MATCHER(typename, properties...) \ 71 MATCHER(Eq##typename, " ") { \ 72 return testing::Matches(Eq##typename(std::get<1>(arg)))(std::get<0>(arg)); \ 73 } \ 74 MATCHER_P(Eq##typename, expected, testing::PrintToString(expected)) { \ 75 return testing::ExplainMatchResult(testing::AllOf(properties), arg, result_listener); \ 76 } 77 78 #define PROPERTY_PRINT(propname) \ 79 if (obj.has_##propname()) { \ 80 *os << #propname << ": " << testing::PrintToString(obj.propname()) << ", "; \ 81 } 82 83 #define REPEATED_PROPERTY_PRINT(propname) \ 84 if (obj.propname##_size() > 0) { \ 85 *os << #propname << ": " << testing::PrintToString(obj.propname()) << ", "; \ 86 } 87 88 /** 89 * Generates a method that teaches GoogleTest how to print a custom type specified by typename 90 * with the given properties. 91 * The equality matcher generated by EQ_MATCHER for the given typename will use this generated 92 * printer method to print the object when the matcher fails. 93 * 94 * Example: For the protos: 95 * message Bar { 96 * optional int32 aa = 1; 97 * } 98 * message Foo { 99 * optional int32 a = 1; 100 * repeated float b = 2; 101 * optional Bar bar = 3; 102 * repeated Bar repeated_bar = 4; 103 * } 104 * This will generate printer methods for them: 105 * TYPE_PRINTER(Bar, PROPERTY_PRINT(aa)); 106 * TYPE_PRINTER(Foo, 107 * PROPERTY_PRINT(a) 108 * PROPERTY_PRINT(b) 109 * PROPERTY_PRINT(bar) 110 * REPEATED_PROPERTY_PRINT(repeated_bar) 111 * ); 112 */ 113 #define TYPE_PRINTER(typename, properties) \ 114 inline void PrintTo(const typename& obj, std::ostream* os) { \ 115 *os << #typename << ": { "; \ 116 properties \ 117 *os << "}"; \ 118 } 119 120 EQ_MATCHER(PackageInfo, 121 PROPERTY_EQ(PackageInfo, version), 122 PROPERTY_EQ(PackageInfo, uid), 123 PROPERTY_EQ(PackageInfo, deleted), 124 PROPERTY_EQ(PackageInfo, truncated_certificate_hash), 125 PROPERTY_EQ(PackageInfo, name_hash), 126 PROPERTY_EQ(PackageInfo, version_string_hash), 127 PROPERTY_EQ(PackageInfo, name), 128 PROPERTY_EQ(PackageInfo, version_string), 129 PROPERTY_EQ(PackageInfo, installer_index), 130 PROPERTY_EQ(PackageInfo, installer_hash), 131 PROPERTY_EQ(PackageInfo, installer) 132 ); 133 TYPE_PRINTER(PackageInfo, 134 PROPERTY_PRINT(version) 135 PROPERTY_PRINT(uid) 136 PROPERTY_PRINT(deleted) 137 PROPERTY_PRINT(truncated_certificate_hash) 138 PROPERTY_PRINT(name_hash) 139 PROPERTY_PRINT(version_string_hash) 140 PROPERTY_PRINT(name) 141 PROPERTY_PRINT(version_string) 142 PROPERTY_PRINT(installer_index) 143 PROPERTY_PRINT(installer_hash) 144 PROPERTY_PRINT(installer) 145 ); 146 147 EQ_MATCHER(AttributionNode, 148 PROPERTY_EQ(AttributionNode, uid), 149 PROPERTY_EQ(AttributionNode, tag) 150 ); 151 TYPE_PRINTER(AttributionNode, 152 PROPERTY_PRINT(uid) 153 PROPERTY_PRINT(tag) 154 ); 155 156 EQ_MATCHER(ScreenStateChanged, PROPERTY_EQ(ScreenStateChanged, state)); 157 TYPE_PRINTER(ScreenStateChanged, PROPERTY_PRINT(state)); 158 159 EQ_MATCHER(TrainExperimentIds, 160 REPEATED_PROPERTY_EQ(TrainExperimentIds, experiment_id) 161 ); 162 TYPE_PRINTER(TrainExperimentIds, REPEATED_PROPERTY_PRINT(experiment_id)); 163 164 EQ_MATCHER(TestAtomReported, 165 REPEATED_PROPERTY_MATCHER(TestAtomReported, attribution_node, EqAttributionNode), 166 PROPERTY_EQ(TestAtomReported, int_field), 167 PROPERTY_EQ(TestAtomReported, long_field), 168 PROPERTY_EQ(TestAtomReported, float_field), 169 PROPERTY_EQ(TestAtomReported, string_field), 170 PROPERTY_EQ(TestAtomReported, boolean_field), 171 PROPERTY_EQ(TestAtomReported, state), 172 PROPERTY_MATCHER(TestAtomReported, bytes_field, EqTrainExperimentIds), 173 REPEATED_PROPERTY_EQ(TestAtomReported, repeated_int_field), 174 REPEATED_PROPERTY_EQ(TestAtomReported, repeated_long_field), 175 REPEATED_PROPERTY_EQ(TestAtomReported, repeated_float_field), 176 REPEATED_PROPERTY_EQ(TestAtomReported, repeated_string_field), 177 REPEATED_PROPERTY_EQ(TestAtomReported, repeated_boolean_field), 178 REPEATED_PROPERTY_EQ(TestAtomReported, repeated_enum_field) 179 ); 180 TYPE_PRINTER(TestAtomReported, 181 REPEATED_PROPERTY_PRINT(attribution_node) 182 PROPERTY_PRINT(int_field) 183 PROPERTY_PRINT(long_field) 184 PROPERTY_PRINT(float_field) 185 PROPERTY_PRINT(string_field) 186 PROPERTY_PRINT(boolean_field) 187 PROPERTY_PRINT(state) 188 PROPERTY_PRINT(bytes_field) 189 REPEATED_PROPERTY_PRINT(repeated_int_field) 190 REPEATED_PROPERTY_PRINT(repeated_long_field) 191 REPEATED_PROPERTY_PRINT(repeated_float_field) 192 REPEATED_PROPERTY_PRINT(repeated_string_field) 193 REPEATED_PROPERTY_PRINT(repeated_boolean_field) 194 REPEATED_PROPERTY_PRINT(repeated_enum_field) 195 ); 196 197 EQ_MATCHER(CpuActiveTime, 198 PROPERTY_EQ(CpuActiveTime, uid), 199 PROPERTY_EQ(CpuActiveTime, time_millis) 200 ); 201 TYPE_PRINTER(CpuActiveTime, 202 PROPERTY_PRINT(uid) 203 PROPERTY_PRINT(time_millis) 204 ); 205 206 EQ_MATCHER(PluggedStateChanged, PROPERTY_EQ(PluggedStateChanged, state)); 207 TYPE_PRINTER(PluggedStateChanged, PROPERTY_PRINT(state)); 208 209 EQ_MATCHER(WakelockStateChanged, 210 REPEATED_PROPERTY_MATCHER(WakelockStateChanged, attribution_node, EqAttributionNode), 211 PROPERTY_EQ(WakelockStateChanged, type), 212 PROPERTY_EQ(WakelockStateChanged, tag), 213 PROPERTY_EQ(WakelockStateChanged, state), 214 PROPERTY_EQ(WakelockStateChanged, process_state) 215 ); 216 TYPE_PRINTER(WakelockStateChanged, 217 REPEATED_PROPERTY_PRINT(attribution_node) 218 PROPERTY_PRINT(type) 219 PROPERTY_PRINT(tag) 220 PROPERTY_PRINT(state) 221 PROPERTY_PRINT(process_state) 222 ); 223 224 EQ_MATCHER(Atom, 225 PROPERTY_MATCHER(Atom, screen_state_changed, EqScreenStateChanged), 226 PROPERTY_MATCHER(Atom, test_atom_reported, EqTestAtomReported), 227 PROPERTY_MATCHER(Atom, wakelock_state_changed, EqWakelockStateChanged) 228 ); 229 TYPE_PRINTER(Atom, 230 PROPERTY_PRINT(screen_state_changed) 231 PROPERTY_PRINT(test_atom_reported) 232 PROPERTY_PRINT(wakelock_state_changed) 233 ); 234 235 EQ_MATCHER(ShellData, 236 REPEATED_PROPERTY_MATCHER(ShellData, atom, EqAtom), 237 REPEATED_PROPERTY_EQ(ShellData, elapsed_timestamp_nanos) 238 ); 239 TYPE_PRINTER(ShellData, 240 REPEATED_PROPERTY_PRINT(atom) 241 REPEATED_PROPERTY_PRINT(elapsed_timestamp_nanos) 242 ); 243 244 // clang-format on 245 246 } // namespace statsd 247 } // namespace os 248 } // namespace android 249