blob: 86f1a39b816d1783fe7ad3009a7c6ae5dd196508 [file] [log] [blame]
Yiwei Zhang16faa5d2018-11-13 18:12:59 -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
17#undef LOG_TAG
18#define LOG_TAG "LibSurfaceFlingerUnittests"
19
20#include <gtest/gtest.h>
21
22#include <log/log.h>
23#include <utils/String16.h>
Yiwei Zhang16faa5d2018-11-13 18:12:59 -080024#include <utils/Vector.h>
25
26#include <random>
27
28#include "TimeStats/TimeStats.h"
29
Lloyd Pique067fe1e2018-12-06 19:44:13 -080030#include "libsurfaceflinger_unittest_main.h"
31
Yiwei Zhang16faa5d2018-11-13 18:12:59 -080032using namespace android::surfaceflinger;
33using namespace google::protobuf;
34
35namespace android {
36namespace {
37
38// clang-format off
39#define FMT_PROTO true
40#define FMT_STRING false
41#define LAYER_ID_0 0
42#define LAYER_ID_1 1
43#define LAYER_ID_INVALID -1
44#define NUM_LAYERS 1
45#define NUM_LAYERS_INVALID "INVALID"
46
47enum InputCommand : int32_t {
48 ENABLE = 0,
49 DISABLE = 1,
50 CLEAR = 2,
51 DUMP_ALL = 3,
52 DUMP_MAXLAYERS_1 = 4,
53 DUMP_MAXLAYERS_INVALID = 5,
54 INPUT_COMMAND_BEGIN = ENABLE,
55 INPUT_COMMAND_END = DUMP_MAXLAYERS_INVALID,
56 INPUT_COMMAND_RANGE = INPUT_COMMAND_END - INPUT_COMMAND_BEGIN + 1,
57};
58
59enum TimeStamp : int32_t {
60 POST = 0,
61 ACQUIRE = 1,
62 ACQUIRE_FENCE = 2,
63 LATCH = 3,
64 DESIRED = 4,
65 PRESENT = 5,
66 PRESENT_FENCE = 6,
67 TIME_STAMP_BEGIN = POST,
68 TIME_STAMP_END = PRESENT,
69 TIME_STAMP_RANGE = TIME_STAMP_END - TIME_STAMP_BEGIN + 1,
70};
71
72static const TimeStamp NORMAL_SEQUENCE[] = {
73 TimeStamp::POST,
74 TimeStamp::ACQUIRE,
75 TimeStamp::LATCH,
76 TimeStamp::DESIRED,
77 TimeStamp::PRESENT,
78};
79
80static const TimeStamp NORMAL_SEQUENCE_2[] = {
81 TimeStamp::POST,
82 TimeStamp::ACQUIRE_FENCE,
83 TimeStamp::LATCH,
84 TimeStamp::DESIRED,
85 TimeStamp::PRESENT_FENCE,
86};
87
88static const TimeStamp UNORDERED_SEQUENCE[] = {
89 TimeStamp::ACQUIRE,
90 TimeStamp::LATCH,
91 TimeStamp::POST,
92 TimeStamp::DESIRED,
93 TimeStamp::PRESENT,
94};
95
96static const TimeStamp INCOMPLETE_SEQUENCE[] = {
97 TimeStamp::POST,
98};
99// clang-format on
100
101class TimeStatsTest : public testing::Test {
102public:
103 TimeStatsTest() {
104 const ::testing::TestInfo* const test_info =
105 ::testing::UnitTest::GetInstance()->current_test_info();
106 ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
107 }
108
109 ~TimeStatsTest() {
110 const ::testing::TestInfo* const test_info =
111 ::testing::UnitTest::GetInstance()->current_test_info();
112 ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
113 }
114
115 std::string inputCommand(InputCommand cmd, bool useProto);
116
117 void setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts);
118
119 int32_t genRandomInt32(int32_t begin, int32_t end);
120
121 template <size_t N>
122 void insertTimeRecord(const TimeStamp (&sequence)[N], int32_t id, uint64_t frameNumber,
123 nsecs_t ts) {
124 for (size_t i = 0; i < N; i++, ts += 1000000) {
125 setTimeStamp(sequence[i], id, frameNumber, ts);
126 }
127 }
128
129 std::mt19937 mRandomEngine = std::mt19937(std::random_device()());
130 std::unique_ptr<TimeStats> mTimeStats = std::make_unique<TimeStats>();
131};
132
133std::string TimeStatsTest::inputCommand(InputCommand cmd, bool useProto) {
134 size_t index = 0;
Yiwei Zhang5434a782018-12-05 18:06:32 -0800135 std::string result;
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800136 Vector<String16> args;
137
138 switch (cmd) {
139 case InputCommand::ENABLE:
140 args.push_back(String16("-enable"));
141 break;
142 case InputCommand::DISABLE:
143 args.push_back(String16("-disable"));
144 break;
145 case InputCommand::CLEAR:
146 args.push_back(String16("-clear"));
147 break;
148 case InputCommand::DUMP_ALL:
149 args.push_back(String16("-dump"));
150 break;
151 case InputCommand::DUMP_MAXLAYERS_1:
152 args.push_back(String16("-dump"));
153 args.push_back(String16("-maxlayers"));
154 args.push_back(String16(std::to_string(NUM_LAYERS).c_str()));
155 break;
156 case InputCommand::DUMP_MAXLAYERS_INVALID:
157 args.push_back(String16("-dump"));
158 args.push_back(String16("-maxlayers"));
159 args.push_back(String16(NUM_LAYERS_INVALID));
160 break;
161 default:
162 ALOGD("Invalid control command");
163 }
164
165 EXPECT_NO_FATAL_FAILURE(mTimeStats->parseArgs(useProto, args, index, result));
Yiwei Zhang5434a782018-12-05 18:06:32 -0800166 return result;
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800167}
168
169static std::string genLayerName(int32_t layerID) {
170 return (layerID < 0 ? "invalid.dummy" : "com.dummy#") + std::to_string(layerID);
171}
172
173void TimeStatsTest::setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts) {
174 switch (type) {
175 case TimeStamp::POST:
176 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPostTime(id, frameNumber, genLayerName(id), ts));
177 break;
178 case TimeStamp::ACQUIRE:
179 ASSERT_NO_FATAL_FAILURE(mTimeStats->setAcquireTime(id, frameNumber, ts));
180 break;
181 case TimeStamp::ACQUIRE_FENCE:
182 ASSERT_NO_FATAL_FAILURE(
183 mTimeStats->setAcquireFence(id, frameNumber, std::make_shared<FenceTime>(ts)));
184 break;
185 case TimeStamp::LATCH:
186 ASSERT_NO_FATAL_FAILURE(mTimeStats->setLatchTime(id, frameNumber, ts));
187 break;
188 case TimeStamp::DESIRED:
189 ASSERT_NO_FATAL_FAILURE(mTimeStats->setDesiredTime(id, frameNumber, ts));
190 break;
191 case TimeStamp::PRESENT:
192 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPresentTime(id, frameNumber, ts));
193 break;
194 case TimeStamp::PRESENT_FENCE:
195 ASSERT_NO_FATAL_FAILURE(
196 mTimeStats->setPresentFence(id, frameNumber, std::make_shared<FenceTime>(ts)));
197 break;
198 default:
199 ALOGD("Invalid timestamp type");
200 }
201}
202
203int32_t TimeStatsTest::genRandomInt32(int32_t begin, int32_t end) {
204 std::uniform_int_distribution<int32_t> distr(begin, end);
205 return distr(mRandomEngine);
206}
207
208TEST_F(TimeStatsTest, canEnableAndDisableTimeStats) {
209 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
210 ASSERT_TRUE(mTimeStats->isEnabled());
211
212 EXPECT_TRUE(inputCommand(InputCommand::DISABLE, FMT_STRING).empty());
213 ASSERT_FALSE(mTimeStats->isEnabled());
214}
215
216TEST_F(TimeStatsTest, canIncreaseGlobalStats) {
217 constexpr size_t TOTAL_FRAMES = 5;
218 constexpr size_t MISSED_FRAMES = 4;
219 constexpr size_t CLIENT_COMPOSITION_FRAMES = 3;
220
221 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
222
223 for (size_t i = 0; i < TOTAL_FRAMES; i++) {
224 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementTotalFrames());
225 }
226 for (size_t i = 0; i < MISSED_FRAMES; i++) {
227 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames());
228 }
229 for (size_t i = 0; i < CLIENT_COMPOSITION_FRAMES; i++) {
230 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionFrames());
231 }
232
233 SFTimeStatsGlobalProto globalProto;
234 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
235
236 ASSERT_TRUE(globalProto.has_total_frames());
237 EXPECT_EQ(TOTAL_FRAMES, globalProto.total_frames());
238 ASSERT_TRUE(globalProto.has_missed_frames());
239 EXPECT_EQ(MISSED_FRAMES, globalProto.missed_frames());
240 ASSERT_TRUE(globalProto.has_client_composition_frames());
241 EXPECT_EQ(CLIENT_COMPOSITION_FRAMES, globalProto.client_composition_frames());
242}
243
244TEST_F(TimeStatsTest, canInsertGlobalPresentToPresent) {
245 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
246
247 ASSERT_NO_FATAL_FAILURE(
248 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(1000000)));
249 ASSERT_NO_FATAL_FAILURE(
250 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(2000000)));
251
252 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(HWC_POWER_MODE_NORMAL));
253 ASSERT_NO_FATAL_FAILURE(
254 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000)));
255 ASSERT_NO_FATAL_FAILURE(
256 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000)));
257
258 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(HWC_POWER_MODE_OFF));
259 ASSERT_NO_FATAL_FAILURE(
260 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(6000000)));
261 ASSERT_NO_FATAL_FAILURE(
262 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(8000000)));
263
264 SFTimeStatsGlobalProto globalProto;
265 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
266
267 ASSERT_EQ(1, globalProto.present_to_present_size());
268 const SFTimeStatsHistogramBucketProto& histogramProto = globalProto.present_to_present().Get(0);
269 EXPECT_EQ(1, histogramProto.frame_count());
270 EXPECT_EQ(2, histogramProto.time_millis());
271}
272
273TEST_F(TimeStatsTest, canInsertOneLayerTimeStats) {
274 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
275
276 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
277 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 2, 2000000);
278
279 SFTimeStatsGlobalProto globalProto;
280 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
281
282 ASSERT_EQ(1, globalProto.stats_size());
283 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
284 ASSERT_TRUE(layerProto.has_layer_name());
285 EXPECT_EQ(genLayerName(LAYER_ID_0), layerProto.layer_name());
286 ASSERT_TRUE(layerProto.has_total_frames());
287 EXPECT_EQ(1, layerProto.total_frames());
288 ASSERT_EQ(6, layerProto.deltas_size());
289 for (const SFTimeStatsDeltaProto& deltaProto : layerProto.deltas()) {
290 ASSERT_EQ(1, deltaProto.histograms_size());
291 const SFTimeStatsHistogramBucketProto& histogramProto = deltaProto.histograms().Get(0);
292 EXPECT_EQ(1, histogramProto.frame_count());
293 if ("post2acquire" == deltaProto.delta_name()) {
294 EXPECT_EQ(1, histogramProto.time_millis());
295 } else if ("post2present" == deltaProto.delta_name()) {
296 EXPECT_EQ(4, histogramProto.time_millis());
297 } else if ("acquire2present" == deltaProto.delta_name()) {
298 EXPECT_EQ(3, histogramProto.time_millis());
299 } else if ("latch2present" == deltaProto.delta_name()) {
300 EXPECT_EQ(2, histogramProto.time_millis());
301 } else if ("desired2present" == deltaProto.delta_name()) {
302 EXPECT_EQ(1, histogramProto.time_millis());
303 } else if ("present2present" == deltaProto.delta_name()) {
304 EXPECT_EQ(1, histogramProto.time_millis());
305 } else {
306 FAIL() << "Unknown delta_name: " << deltaProto.delta_name();
307 }
308 }
309}
310
311TEST_F(TimeStatsTest, canNotInsertInvalidLayerNameTimeStats) {
312 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
313
314 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_INVALID, 1, 1000000);
315 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_INVALID, 2, 2000000);
316
317 SFTimeStatsGlobalProto globalProto;
318 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
319
320 ASSERT_EQ(0, globalProto.stats_size());
321}
322
323TEST_F(TimeStatsTest, canInsertMultipleLayersTimeStats) {
324 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
325
326 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
327 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 1000000);
328 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
329 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 2000000);
330
331 SFTimeStatsGlobalProto globalProto;
332 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
333
334 EXPECT_EQ(2, globalProto.stats_size());
335}
336
337TEST_F(TimeStatsTest, canInsertUnorderedLayerTimeStats) {
338 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
339
340 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
341 insertTimeRecord(UNORDERED_SEQUENCE, LAYER_ID_0, 2, 2000000);
342
343 SFTimeStatsGlobalProto globalProto;
344 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
345
346 ASSERT_EQ(1, globalProto.stats_size());
347 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
348 ASSERT_TRUE(layerProto.has_layer_name());
349 EXPECT_EQ(genLayerName(LAYER_ID_0), layerProto.layer_name());
350 ASSERT_TRUE(layerProto.has_total_frames());
351 EXPECT_EQ(1, layerProto.total_frames());
352 ASSERT_EQ(6, layerProto.deltas_size());
353 for (const SFTimeStatsDeltaProto& deltaProto : layerProto.deltas()) {
354 ASSERT_EQ(1, deltaProto.histograms_size());
355 const SFTimeStatsHistogramBucketProto& histogramProto = deltaProto.histograms().Get(0);
356 EXPECT_EQ(1, histogramProto.frame_count());
357 if ("post2acquire" == deltaProto.delta_name()) {
358 EXPECT_EQ(0, histogramProto.time_millis());
359 } else if ("post2present" == deltaProto.delta_name()) {
360 EXPECT_EQ(2, histogramProto.time_millis());
361 } else if ("acquire2present" == deltaProto.delta_name()) {
362 EXPECT_EQ(2, histogramProto.time_millis());
363 } else if ("latch2present" == deltaProto.delta_name()) {
364 EXPECT_EQ(2, histogramProto.time_millis());
365 } else if ("desired2present" == deltaProto.delta_name()) {
366 EXPECT_EQ(1, histogramProto.time_millis());
367 } else if ("present2present" == deltaProto.delta_name()) {
368 EXPECT_EQ(1, histogramProto.time_millis());
369 } else {
370 FAIL() << "Unknown delta_name: " << deltaProto.delta_name();
371 }
372 }
373}
374
375TEST_F(TimeStatsTest, canRemoveTimeRecord) {
376 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
377
378 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
379 insertTimeRecord(INCOMPLETE_SEQUENCE, LAYER_ID_0, 2, 2000000);
380 ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(0, 2));
381 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000);
382
383 SFTimeStatsGlobalProto globalProto;
384 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
385
386 ASSERT_EQ(1, globalProto.stats_size());
387 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
388 ASSERT_TRUE(layerProto.has_total_frames());
389 EXPECT_EQ(1, layerProto.total_frames());
390}
391
392TEST_F(TimeStatsTest, canRecoverFromIncompleteTimeRecordError) {
393 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
394
395 uint64_t frameNumber = 1;
396 nsecs_t ts = 1000000;
397 insertTimeRecord(INCOMPLETE_SEQUENCE, LAYER_ID_0, 1, 1000000);
398 for (size_t i = 0; i < TimeStats::MAX_NUM_TIME_RECORDS + 2; i++) {
399 frameNumber++;
400 ts += 1000000;
401 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, frameNumber, ts);
402 }
403
404 SFTimeStatsGlobalProto globalProto;
405 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
406
407 ASSERT_EQ(1, globalProto.stats_size());
408 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
409 ASSERT_TRUE(layerProto.has_total_frames());
410 EXPECT_EQ(1, layerProto.total_frames());
411}
412
413TEST_F(TimeStatsTest, layerTimeStatsOnDestroy) {
414 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
415
416 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
417 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
418 ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(0));
419 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000);
420
421 SFTimeStatsGlobalProto globalProto;
422 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
423
424 ASSERT_EQ(1, globalProto.stats_size());
425 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
426 ASSERT_TRUE(layerProto.has_total_frames());
427 EXPECT_EQ(1, layerProto.total_frames());
428}
429
430TEST_F(TimeStatsTest, canClearTimeStats) {
431 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
432
433 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementTotalFrames());
434 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames());
435 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionFrames());
436 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(HWC_POWER_MODE_NORMAL));
437 ASSERT_NO_FATAL_FAILURE(
438 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(1000000)));
439 ASSERT_NO_FATAL_FAILURE(
440 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(2000000)));
441 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
442 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
443
444 EXPECT_TRUE(inputCommand(InputCommand::CLEAR, FMT_STRING).empty());
445
446 SFTimeStatsGlobalProto globalProto;
447 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
448
449 EXPECT_EQ(0, globalProto.total_frames());
450 EXPECT_EQ(0, globalProto.missed_frames());
451 EXPECT_EQ(0, globalProto.client_composition_frames());
452 EXPECT_EQ(0, globalProto.present_to_present_size());
453 EXPECT_EQ(0, globalProto.stats_size());
454}
455
456TEST_F(TimeStatsTest, canDumpWithMaxLayers) {
457 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
458
459 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
460 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 1000000);
461 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
462 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 2000000);
463 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 3, 2000000);
464
465 SFTimeStatsGlobalProto globalProto;
466 ASSERT_TRUE(
467 globalProto.ParseFromString(inputCommand(InputCommand::DUMP_MAXLAYERS_1, FMT_PROTO)));
468
469 ASSERT_EQ(1, globalProto.stats_size());
470 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
471 ASSERT_TRUE(layerProto.has_layer_name());
472 EXPECT_EQ(genLayerName(LAYER_ID_1), layerProto.layer_name());
473 ASSERT_TRUE(layerProto.has_total_frames());
474 EXPECT_EQ(2, layerProto.total_frames());
475}
476
477TEST_F(TimeStatsTest, canDumpWithInvalidMaxLayers) {
478 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
479
480 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
481 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
482
483 SFTimeStatsGlobalProto globalProto;
484 ASSERT_TRUE(globalProto.ParseFromString(
485 inputCommand(InputCommand::DUMP_MAXLAYERS_INVALID, FMT_PROTO)));
486
487 ASSERT_EQ(0, globalProto.stats_size());
488}
489
490TEST_F(TimeStatsTest, canSurviveMonkey) {
Lloyd Pique067fe1e2018-12-06 19:44:13 -0800491 if (g_noSlowTests) {
492 GTEST_SKIP();
493 }
494
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800495 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
496
497 for (size_t i = 0; i < 10000000; ++i) {
498 const int32_t layerID = genRandomInt32(-1, 10);
499 const int32_t frameNumber = genRandomInt32(1, 10);
500 switch (genRandomInt32(0, 100)) {
501 case 0:
502 ALOGV("removeTimeRecord");
503 ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(layerID, frameNumber));
504 continue;
505 case 1:
506 ALOGV("onDestroy");
507 ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(layerID));
508 continue;
509 }
510 TimeStamp type = static_cast<TimeStamp>(genRandomInt32(TIME_STAMP_BEGIN, TIME_STAMP_END));
511 const int32_t ts = genRandomInt32(1, 1000000000);
512 ALOGV("type[%d], layerID[%d], frameNumber[%d], ts[%d]", type, layerID, frameNumber, ts);
513 setTimeStamp(type, layerID, frameNumber, ts);
514 }
515}
516
517} // namespace
518} // namespace android