blob: fe762c99972ebd07c4e7c779f27ca3a594870f2c [file] [log] [blame]
Adam Stonecea91ce2018-01-22 19:23:28 -08001/*
2 * Copyright 2018 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
Adam Stonefb679e32018-02-07 10:25:48 -080017#define LOG_TAG "DrmMetricsTest"
Adam Stonecea91ce2018-01-22 19:23:28 -080018#include "DrmMetrics.h"
19
Adam Stonefb679e32018-02-07 10:25:48 -080020#include <binder/PersistableBundle.h>
21#include <google/protobuf/text_format.h>
22#include <google/protobuf/util/message_differencer.h>
23#include <gtest/gtest.h>
24#include <utils/Log.h>
25
26#include "protos/metrics.pb.h"
27
28using ::android::drm_metrics::DrmFrameworkMetrics;
Adam Stonecea91ce2018-01-22 19:23:28 -080029using ::android::hardware::drm::V1_0::EventType;
30using ::android::hardware::drm::V1_0::KeyStatusType;
Adam Stone568b3c42018-01-31 12:57:16 -080031using ::android::os::PersistableBundle;
Adam Stonefb679e32018-02-07 10:25:48 -080032using ::google::protobuf::util::MessageDifferencer;
33using ::google::protobuf::TextFormat;
Adam Stonecea91ce2018-01-22 19:23:28 -080034
35namespace android {
36
37/**
38 * Unit tests for the MediaDrmMetrics class.
39 */
Adam Stonefb679e32018-02-07 10:25:48 -080040class MediaDrmMetricsTest : public ::testing::Test {};
41
42/**
43 * This derived class mocks the clock for testing purposes.
44 */
45class FakeMediaDrmMetrics : public MediaDrmMetrics {
46 public:
47 FakeMediaDrmMetrics() : MediaDrmMetrics(), time_(0) {};
48
49 int64_t GetCurrentTimeMs() { return time_++; }
50 int64_t time_;
Adam Stonecea91ce2018-01-22 19:23:28 -080051};
52
53TEST_F(MediaDrmMetricsTest, EmptySuccess) {
54 MediaDrmMetrics metrics;
Adam Stone568b3c42018-01-31 12:57:16 -080055 PersistableBundle bundle;
Adam Stonecea91ce2018-01-22 19:23:28 -080056
Adam Stone568b3c42018-01-31 12:57:16 -080057 metrics.Export(&bundle);
58 EXPECT_TRUE(bundle.empty());
Adam Stonecea91ce2018-01-22 19:23:28 -080059}
60
61TEST_F(MediaDrmMetricsTest, AllValuesSuccessCounts) {
62 MediaDrmMetrics metrics;
63
64 metrics.mOpenSessionCounter.Increment(OK);
65 metrics.mCloseSessionCounter.Increment(OK);
66
67 {
Adam Stonefb679e32018-02-07 10:25:48 -080068 EventTimer<status_t> get_key_request_timer(&metrics.mGetKeyRequestTimeUs);
Adam Stonecea91ce2018-01-22 19:23:28 -080069 EventTimer<status_t> provide_key_response_timer(
Adam Stonefb679e32018-02-07 10:25:48 -080070 &metrics.mProvideKeyResponseTimeUs);
Adam Stonecea91ce2018-01-22 19:23:28 -080071 get_key_request_timer.SetAttribute(OK);
72 provide_key_response_timer.SetAttribute(OK);
73 }
74
75 metrics.mGetProvisionRequestCounter.Increment(OK);
76 metrics.mProvideProvisionResponseCounter.Increment(OK);
77 metrics.mGetDeviceUniqueIdCounter.Increment(OK);
78
79 metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::USABLE);
80 metrics.mEventCounter.Increment(EventType::PROVISION_REQUIRED);
81
Adam Stone568b3c42018-01-31 12:57:16 -080082 PersistableBundle bundle;
Adam Stonecea91ce2018-01-22 19:23:28 -080083
Adam Stone568b3c42018-01-31 12:57:16 -080084 metrics.Export(&bundle);
85 EXPECT_EQ(11U, bundle.size());
Adam Stonecea91ce2018-01-22 19:23:28 -080086
87 // Verify the list of pairs of int64 metrics.
88 std::vector<std::pair<std::string, int64_t>> expected_values = {
Adam Stone4bea53c2018-01-24 21:44:58 -080089 { "drm.mediadrm.open_session.ok.count", 1 },
90 { "drm.mediadrm.close_session.ok.count", 1 },
91 { "drm.mediadrm.get_key_request.ok.count", 1 },
92 { "drm.mediadrm.provide_key_response.ok.count", 1 },
93 { "drm.mediadrm.get_provision_request.ok.count", 1 },
94 { "drm.mediadrm.provide_provision_response.ok.count", 1 },
95 { "drm.mediadrm.key_status_change.USABLE.count", 1 },
96 { "drm.mediadrm.event.PROVISION_REQUIRED.count", 1 },
97 { "drm.mediadrm.get_device_unique_id.ok.count", 1 }};
Adam Stonecea91ce2018-01-22 19:23:28 -080098 for (const auto& expected_pair : expected_values) {
Adam Stone568b3c42018-01-31 12:57:16 -080099 String16 key(expected_pair.first.c_str());
Adam Stonecea91ce2018-01-22 19:23:28 -0800100 int64_t value = -1;
Adam Stone568b3c42018-01-31 12:57:16 -0800101 EXPECT_TRUE(bundle.getLong(key, &value))
102 << "Unexpected error retrieviing key: " << key;
Adam Stonecea91ce2018-01-22 19:23:28 -0800103 EXPECT_EQ(expected_pair.second, value)
Adam Stone568b3c42018-01-31 12:57:16 -0800104 << "Unexpected value for " << expected_pair.first << ". " << value;
Adam Stonecea91ce2018-01-22 19:23:28 -0800105 }
106
107 // Validate timing values exist.
Adam Stone568b3c42018-01-31 12:57:16 -0800108 String16 get_key_request_key(
109 "drm.mediadrm.get_key_request.ok.average_time_micros");
110 String16 provide_key_response_key(
111 "drm.mediadrm.provide_key_response.ok.average_time_micros");
Adam Stonecea91ce2018-01-22 19:23:28 -0800112 int64_t value = -1;
Adam Stone568b3c42018-01-31 12:57:16 -0800113 EXPECT_TRUE(bundle.getLong(get_key_request_key, &value));
Adam Stonecea91ce2018-01-22 19:23:28 -0800114 EXPECT_GE(value, 0);
Adam Stonecea91ce2018-01-22 19:23:28 -0800115 value = -1;
Adam Stone568b3c42018-01-31 12:57:16 -0800116 EXPECT_TRUE(bundle.getLong(provide_key_response_key, &value));
Adam Stonecea91ce2018-01-22 19:23:28 -0800117 EXPECT_GE(value, 0);
118}
119
120TEST_F(MediaDrmMetricsTest, AllValuesFull) {
121 MediaDrmMetrics metrics;
122
123 metrics.mOpenSessionCounter.Increment(OK);
124 metrics.mOpenSessionCounter.Increment(UNEXPECTED_NULL);
125
126 metrics.mCloseSessionCounter.Increment(OK);
127 metrics.mCloseSessionCounter.Increment(UNEXPECTED_NULL);
128
129 for (status_t s : {OK, UNEXPECTED_NULL}) {
130 {
Adam Stonefb679e32018-02-07 10:25:48 -0800131 EventTimer<status_t> get_key_request_timer(&metrics.mGetKeyRequestTimeUs);
Adam Stonecea91ce2018-01-22 19:23:28 -0800132 EventTimer<status_t> provide_key_response_timer(
Adam Stonefb679e32018-02-07 10:25:48 -0800133 &metrics.mProvideKeyResponseTimeUs);
Adam Stonecea91ce2018-01-22 19:23:28 -0800134 get_key_request_timer.SetAttribute(s);
135 provide_key_response_timer.SetAttribute(s);
136 }
137 }
138
139 metrics.mGetProvisionRequestCounter.Increment(OK);
140 metrics.mGetProvisionRequestCounter.Increment(UNEXPECTED_NULL);
141 metrics.mProvideProvisionResponseCounter.Increment(OK);
142 metrics.mProvideProvisionResponseCounter.Increment(UNEXPECTED_NULL);
143 metrics.mGetDeviceUniqueIdCounter.Increment(OK);
144 metrics.mGetDeviceUniqueIdCounter.Increment(UNEXPECTED_NULL);
145
146 metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::USABLE);
147 metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::EXPIRED);
148 metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::OUTPUTNOTALLOWED);
149 metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::STATUSPENDING);
150 metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::INTERNALERROR);
151 metrics.mEventCounter.Increment(EventType::PROVISION_REQUIRED);
152 metrics.mEventCounter.Increment(EventType::KEY_NEEDED);
153 metrics.mEventCounter.Increment(EventType::KEY_EXPIRED);
154 metrics.mEventCounter.Increment(EventType::VENDOR_DEFINED);
155 metrics.mEventCounter.Increment(EventType::SESSION_RECLAIMED);
156
Adam Stonefb679e32018-02-07 10:25:48 -0800157 android::Vector<uint8_t> sessionId1;
158 sessionId1.push_back(1);
159 sessionId1.push_back(2);
160 android::Vector<uint8_t> sessionId2;
161 sessionId2.push_back(3);
162 sessionId2.push_back(4);
163 String16 hexSessionId1("0102");
164 String16 hexSessionId2("0304");
165
166 metrics.SetSessionStart(sessionId1);
167 metrics.SetSessionStart(sessionId2);
168 metrics.SetSessionEnd(sessionId2);
169 metrics.SetSessionEnd(sessionId1);
170
Adam Stone568b3c42018-01-31 12:57:16 -0800171 PersistableBundle bundle;
172 metrics.Export(&bundle);
Adam Stonefb679e32018-02-07 10:25:48 -0800173 EXPECT_EQ(35U, bundle.size());
Adam Stonecea91ce2018-01-22 19:23:28 -0800174
175 // Verify the list of pairs of int64 metrics.
176 std::vector<std::pair<std::string, int64_t>> expected_values = {
Adam Stone4bea53c2018-01-24 21:44:58 -0800177 { "drm.mediadrm.open_session.ok.count", 1 },
178 { "drm.mediadrm.close_session.ok.count", 1 },
179 { "drm.mediadrm.get_key_request.ok.count", 1 },
180 { "drm.mediadrm.provide_key_response.ok.count", 1 },
181 { "drm.mediadrm.get_provision_request.ok.count", 1 },
182 { "drm.mediadrm.provide_provision_response.ok.count", 1 },
183 { "drm.mediadrm.get_device_unique_id.ok.count", 1 },
184 { "drm.mediadrm.open_session.error.count", 1 },
185 { "drm.mediadrm.close_session.error.count", 1 },
186 { "drm.mediadrm.get_key_request.error.count", 1 },
187 { "drm.mediadrm.provide_key_response.error.count", 1 },
188 { "drm.mediadrm.get_provision_request.error.count", 1 },
189 { "drm.mediadrm.provide_provision_response.error.count", 1 },
190 { "drm.mediadrm.get_device_unique_id.error.count", 1 },
191 { "drm.mediadrm.key_status_change.USABLE.count", 1 },
192 { "drm.mediadrm.key_status_change.EXPIRED.count", 1 },
193 { "drm.mediadrm.key_status_change.OUTPUT_NOT_ALLOWED.count", 1 },
194 { "drm.mediadrm.key_status_change.STATUS_PENDING.count", 1 },
195 { "drm.mediadrm.key_status_change.INTERNAL_ERROR.count", 1 },
196 { "drm.mediadrm.event.PROVISION_REQUIRED.count", 1 },
197 { "drm.mediadrm.event.KEY_NEEDED.count", 1 },
198 { "drm.mediadrm.event.KEY_EXPIRED.count", 1 },
199 { "drm.mediadrm.event.VENDOR_DEFINED.count", 1 },
200 { "drm.mediadrm.event.SESSION_RECLAIMED.count", 1 }};
Adam Stonecea91ce2018-01-22 19:23:28 -0800201 for (const auto& expected_pair : expected_values) {
Adam Stone568b3c42018-01-31 12:57:16 -0800202 String16 key(expected_pair.first.c_str());
Adam Stonecea91ce2018-01-22 19:23:28 -0800203 int64_t value = -1;
Adam Stone568b3c42018-01-31 12:57:16 -0800204 EXPECT_TRUE(bundle.getLong(key, &value))
205 << "Unexpected error retrieviing key: " << key;
Adam Stonecea91ce2018-01-22 19:23:28 -0800206 EXPECT_EQ(expected_pair.second, value)
Adam Stone568b3c42018-01-31 12:57:16 -0800207 << "Unexpected value for " << expected_pair.first << ". " << value;
208 }
209
210 // Verify the error lists
211 std::vector<std::pair<std::string, std::vector<int64_t>>> expected_vector_values = {
212 { "drm.mediadrm.close_session.error.list", { UNEXPECTED_NULL } },
213 { "drm.mediadrm.get_device_unique_id.error.list", { UNEXPECTED_NULL } },
214 { "drm.mediadrm.get_key_request.error.list", { UNEXPECTED_NULL } },
215 { "drm.mediadrm.get_provision_request.error.list", { UNEXPECTED_NULL } },
216 { "drm.mediadrm.open_session.error.list", { UNEXPECTED_NULL } },
217 { "drm.mediadrm.provide_key_response.error.list", { UNEXPECTED_NULL } },
218 { "drm.mediadrm.provide_provision_response.error.list", { UNEXPECTED_NULL } }};
219 for (const auto& expected_pair : expected_vector_values) {
220 String16 key(expected_pair.first.c_str());
221 std::vector<int64_t> values;
222 EXPECT_TRUE(bundle.getLongVector(key, &values))
223 << "Unexpected error retrieviing key: " << key;
224 for (auto expected : expected_pair.second) {
225 EXPECT_TRUE(std::find(values.begin(), values.end(), expected) != values.end())
226 << "Could not find " << expected << " for key " << expected_pair.first;
227 }
Adam Stonecea91ce2018-01-22 19:23:28 -0800228 }
229
Adam Stonefb679e32018-02-07 10:25:48 -0800230 // Verify the lifespans
231 PersistableBundle start_times;
232 PersistableBundle end_times;
233 String16 start_time_key("drm.mediadrm.session_start_times_ms");
234 String16 end_time_key("drm.mediadrm.session_end_times_ms");
235 ASSERT_TRUE(bundle.getPersistableBundle(start_time_key, &start_times));
236 ASSERT_TRUE(bundle.getPersistableBundle(end_time_key, &end_times));
237 EXPECT_EQ(2U, start_times.size());
238 EXPECT_EQ(2U, end_times.size());
239 int64_t start_time, end_time;
240 for (const auto& sid : { hexSessionId1, hexSessionId2 }) {
241 start_time = -1;
242 end_time = -1;
243 EXPECT_TRUE(start_times.getLong(sid, &start_time));
244 EXPECT_TRUE(end_times.getLong(sid, &end_time));
245 EXPECT_GT(start_time, 0);
246 EXPECT_GE(end_time, start_time);
247 }
248
Adam Stonecea91ce2018-01-22 19:23:28 -0800249 // Validate timing values exist.
Adam Stone568b3c42018-01-31 12:57:16 -0800250 String16 get_key_request_key(
251 "drm.mediadrm.get_key_request.ok.average_time_micros");
252 String16 provide_key_response_key(
253 "drm.mediadrm.provide_key_response.ok.average_time_micros");
Adam Stonecea91ce2018-01-22 19:23:28 -0800254 int64_t value = -1;
Adam Stone568b3c42018-01-31 12:57:16 -0800255 EXPECT_TRUE(bundle.getLong(get_key_request_key, &value));
Adam Stonecea91ce2018-01-22 19:23:28 -0800256 EXPECT_GE(value, 0);
Adam Stonecea91ce2018-01-22 19:23:28 -0800257 value = -1;
Adam Stone568b3c42018-01-31 12:57:16 -0800258 EXPECT_TRUE(bundle.getLong(provide_key_response_key, &value));
Adam Stonecea91ce2018-01-22 19:23:28 -0800259 EXPECT_GE(value, 0);
260}
261
Adam Stonefb679e32018-02-07 10:25:48 -0800262
263TEST_F(MediaDrmMetricsTest, CounterValuesProtoSerialization) {
264 MediaDrmMetrics metrics;
265
266 metrics.mOpenSessionCounter.Increment(OK);
267 metrics.mOpenSessionCounter.Increment(UNEXPECTED_NULL);
268 metrics.mCloseSessionCounter.Increment(OK);
269 metrics.mCloseSessionCounter.Increment(UNEXPECTED_NULL);
270
271 metrics.mGetProvisionRequestCounter.Increment(OK);
272 metrics.mGetProvisionRequestCounter.Increment(UNEXPECTED_NULL);
273 metrics.mProvideProvisionResponseCounter.Increment(OK);
274 metrics.mProvideProvisionResponseCounter.Increment(UNEXPECTED_NULL);
275 metrics.mGetDeviceUniqueIdCounter.Increment(OK);
276 metrics.mGetDeviceUniqueIdCounter.Increment(UNEXPECTED_NULL);
277
278 metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::USABLE);
279 metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::EXPIRED);
280 metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::OUTPUTNOTALLOWED);
281 metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::STATUSPENDING);
282 metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::INTERNALERROR);
283 metrics.mEventCounter.Increment(EventType::PROVISION_REQUIRED);
284 metrics.mEventCounter.Increment(EventType::KEY_NEEDED);
285 metrics.mEventCounter.Increment(EventType::KEY_EXPIRED);
286 metrics.mEventCounter.Increment(EventType::VENDOR_DEFINED);
287 metrics.mEventCounter.Increment(EventType::SESSION_RECLAIMED);
288
289 std::string serializedMetrics;
290 ASSERT_EQ(OK, metrics.GetSerializedMetrics(&serializedMetrics));
291
292 DrmFrameworkMetrics metricsProto;
293 ASSERT_TRUE(metricsProto.ParseFromString(serializedMetrics));
294
295 std::string expectedMetrics =
296 "open_session_counter { count: 1 attributes { error_code: -0x7FFFFFF8 } } "
297 "open_session_counter { count: 1 attributes { error_code: 0 } } "
298 "close_session_counter { count: 1 attributes { error_code: -0x7FFFFFF8 } } "
299 "close_session_counter { count: 1 attributes { error_code: 0 } } "
300 "get_provisioning_request_counter { count: 1 attributes { error_code: -0x7FFFFFF8 } } "
301 "get_provisioning_request_counter { count: 1 attributes { error_code: 0 } } "
302 "provide_provisioning_response_counter { count: 1 attributes { error_code: -0x7ffffff8 } } "
303 "provide_provisioning_response_counter { count: 1 attributes { error_code: 0 } } "
304 "get_device_unique_id_counter { count: 1 attributes { error_code: -0x7ffffff8 } } "
305 "get_device_unique_id_counter { count: 1 attributes { error_code: 0 } } "
306 "key_status_change_counter { count: 1 attributes { key_status_type: 0 } } "
307 "key_status_change_counter { count: 1 attributes { key_status_type: 1 } } "
308 "key_status_change_counter { count: 1 attributes { key_status_type: 2 } } "
309 "key_status_change_counter { count: 1 attributes { key_status_type: 3 } } "
310 "key_status_change_counter { count: 1 attributes { key_status_type: 4 } } "
311 "event_callback_counter { count: 1 attributes { event_type: 0 } } "
312 "event_callback_counter { count: 1 attributes { event_type: 1 } } "
313 "event_callback_counter { count: 1 attributes { event_type: 2 } } "
314 "event_callback_counter { count: 1 attributes { event_type: 3 } } "
315 "event_callback_counter { count: 1 attributes { event_type: 4 } } ";
316
317 DrmFrameworkMetrics expectedMetricsProto;
318 ASSERT_TRUE(TextFormat::MergeFromString(expectedMetrics, &expectedMetricsProto));
319
320 std::string diffString;
321 MessageDifferencer differ;
322 differ.ReportDifferencesToString(&diffString);
323 ASSERT_TRUE(differ.Compare(expectedMetricsProto, metricsProto))
324 << diffString;
325}
326
327TEST_F(MediaDrmMetricsTest, TimeMetricsProtoSerialization) {
328 MediaDrmMetrics metrics;
329
330 for (status_t s : {OK, UNEXPECTED_NULL}) {
331 double time = 0;
332 for (int i = 0; i < 5; i++) {
333 time += 1.0;
334 metrics.mGetKeyRequestTimeUs.Record(time, s);
335 metrics.mProvideKeyResponseTimeUs.Record(time, s);
336 }
337 }
338
339 std::string serializedMetrics;
340 ASSERT_EQ(OK, metrics.GetSerializedMetrics(&serializedMetrics));
341
342 DrmFrameworkMetrics metricsProto;
343 ASSERT_TRUE(metricsProto.ParseFromString(serializedMetrics));
344
345 std::string expectedMetrics =
346 "get_key_request_timing { "
347 " min: 1 max: 5 mean: 3.5 variance: 1 operation_count: 5 "
348 " attributes { error_code: -0x7FFFFFF8 } "
349 "} "
350 "get_key_request_timing { "
351 " min: 1 max: 5 mean: 3.5 variance: 1 operation_count: 5 "
352 " attributes { error_code: 0 } "
353 "} "
354 "provide_key_response_timing { "
355 " min: 1 max: 5 mean: 3.5 variance: 1 operation_count: 5 "
356 " attributes { error_code: -0x7FFFFFF8 } "
357 "} "
358 "provide_key_response_timing { "
359 " min: 1 max: 5 mean: 3.5 variance: 1 operation_count: 5 "
360 " attributes { error_code: 0 } "
361 "} ";
362
363 DrmFrameworkMetrics expectedMetricsProto;
364 ASSERT_TRUE(TextFormat::MergeFromString(expectedMetrics, &expectedMetricsProto));
365
366 std::string diffString;
367 MessageDifferencer differ;
368 differ.ReportDifferencesToString(&diffString);
369 ASSERT_TRUE(differ.Compare(expectedMetricsProto, metricsProto))
370 << diffString;
371}
372
373TEST_F(MediaDrmMetricsTest, SessionLifetimeProtoSerialization) {
374 // Use the fake so the clock is predictable;
375 FakeMediaDrmMetrics metrics;
376
377 android::Vector<uint8_t> sessionId1;
378 sessionId1.push_back(1);
379 sessionId1.push_back(2);
380 android::Vector<uint8_t> sessionId2;
381 sessionId2.push_back(3);
382 sessionId2.push_back(4);
383
384 metrics.SetSessionStart(sessionId1);
385 metrics.SetSessionStart(sessionId2);
386 metrics.SetSessionEnd(sessionId2);
387 metrics.SetSessionEnd(sessionId1);
388
389 std::string serializedMetrics;
390 ASSERT_EQ(OK, metrics.GetSerializedMetrics(&serializedMetrics));
391
392 DrmFrameworkMetrics metricsProto;
393 ASSERT_TRUE(metricsProto.ParseFromString(serializedMetrics));
394
395 std::string expectedMetrics =
396 "session_lifetimes: { "
397 " key: '0102' "
398 " value { start_time_ms: 0 end_time_ms: 3 } "
399 "} "
400 "session_lifetimes: { "
401 " key: '0304' "
402 " value { start_time_ms: 1 end_time_ms: 2 } "
403 "} ";
404
405 DrmFrameworkMetrics expectedMetricsProto;
406 ASSERT_TRUE(TextFormat::MergeFromString(expectedMetrics, &expectedMetricsProto));
407
408 std::string diffString;
409 MessageDifferencer differ;
410 differ.ReportDifferencesToString(&diffString);
411 ASSERT_TRUE(differ.Compare(expectedMetricsProto, metricsProto))
412 << diffString;
413}
414
Adam Stonecea91ce2018-01-22 19:23:28 -0800415} // namespace android