blob: 0f95cf910b8c82e8d698f2a1e84072ba8e1b7144 [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) {
Yiwei Zhang5434a782018-12-05 18:06:32 -0800134 std::string result;
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800135 Vector<String16> args;
136
137 switch (cmd) {
138 case InputCommand::ENABLE:
139 args.push_back(String16("-enable"));
140 break;
141 case InputCommand::DISABLE:
142 args.push_back(String16("-disable"));
143 break;
144 case InputCommand::CLEAR:
145 args.push_back(String16("-clear"));
146 break;
147 case InputCommand::DUMP_ALL:
148 args.push_back(String16("-dump"));
149 break;
150 case InputCommand::DUMP_MAXLAYERS_1:
151 args.push_back(String16("-dump"));
152 args.push_back(String16("-maxlayers"));
153 args.push_back(String16(std::to_string(NUM_LAYERS).c_str()));
154 break;
155 case InputCommand::DUMP_MAXLAYERS_INVALID:
156 args.push_back(String16("-dump"));
157 args.push_back(String16("-maxlayers"));
158 args.push_back(String16(NUM_LAYERS_INVALID));
159 break;
160 default:
161 ALOGD("Invalid control command");
162 }
163
Dominik Laskowskic2867142019-01-21 11:33:38 -0800164 EXPECT_NO_FATAL_FAILURE(mTimeStats->parseArgs(useProto, args, result));
Yiwei Zhang5434a782018-12-05 18:06:32 -0800165 return result;
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800166}
167
168static std::string genLayerName(int32_t layerID) {
169 return (layerID < 0 ? "invalid.dummy" : "com.dummy#") + std::to_string(layerID);
170}
171
172void TimeStatsTest::setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts) {
173 switch (type) {
174 case TimeStamp::POST:
175 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPostTime(id, frameNumber, genLayerName(id), ts));
176 break;
177 case TimeStamp::ACQUIRE:
178 ASSERT_NO_FATAL_FAILURE(mTimeStats->setAcquireTime(id, frameNumber, ts));
179 break;
180 case TimeStamp::ACQUIRE_FENCE:
181 ASSERT_NO_FATAL_FAILURE(
182 mTimeStats->setAcquireFence(id, frameNumber, std::make_shared<FenceTime>(ts)));
183 break;
184 case TimeStamp::LATCH:
185 ASSERT_NO_FATAL_FAILURE(mTimeStats->setLatchTime(id, frameNumber, ts));
186 break;
187 case TimeStamp::DESIRED:
188 ASSERT_NO_FATAL_FAILURE(mTimeStats->setDesiredTime(id, frameNumber, ts));
189 break;
190 case TimeStamp::PRESENT:
191 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPresentTime(id, frameNumber, ts));
192 break;
193 case TimeStamp::PRESENT_FENCE:
194 ASSERT_NO_FATAL_FAILURE(
195 mTimeStats->setPresentFence(id, frameNumber, std::make_shared<FenceTime>(ts)));
196 break;
197 default:
198 ALOGD("Invalid timestamp type");
199 }
200}
201
202int32_t TimeStatsTest::genRandomInt32(int32_t begin, int32_t end) {
203 std::uniform_int_distribution<int32_t> distr(begin, end);
204 return distr(mRandomEngine);
205}
206
207TEST_F(TimeStatsTest, canEnableAndDisableTimeStats) {
208 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
209 ASSERT_TRUE(mTimeStats->isEnabled());
210
211 EXPECT_TRUE(inputCommand(InputCommand::DISABLE, FMT_STRING).empty());
212 ASSERT_FALSE(mTimeStats->isEnabled());
213}
214
215TEST_F(TimeStatsTest, canIncreaseGlobalStats) {
216 constexpr size_t TOTAL_FRAMES = 5;
217 constexpr size_t MISSED_FRAMES = 4;
218 constexpr size_t CLIENT_COMPOSITION_FRAMES = 3;
219
220 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
221
222 for (size_t i = 0; i < TOTAL_FRAMES; i++) {
223 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementTotalFrames());
224 }
225 for (size_t i = 0; i < MISSED_FRAMES; i++) {
226 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames());
227 }
228 for (size_t i = 0; i < CLIENT_COMPOSITION_FRAMES; i++) {
229 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionFrames());
230 }
231
232 SFTimeStatsGlobalProto globalProto;
233 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
234
235 ASSERT_TRUE(globalProto.has_total_frames());
236 EXPECT_EQ(TOTAL_FRAMES, globalProto.total_frames());
237 ASSERT_TRUE(globalProto.has_missed_frames());
238 EXPECT_EQ(MISSED_FRAMES, globalProto.missed_frames());
239 ASSERT_TRUE(globalProto.has_client_composition_frames());
240 EXPECT_EQ(CLIENT_COMPOSITION_FRAMES, globalProto.client_composition_frames());
241}
242
243TEST_F(TimeStatsTest, canInsertGlobalPresentToPresent) {
244 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
245
246 ASSERT_NO_FATAL_FAILURE(
247 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(1000000)));
248 ASSERT_NO_FATAL_FAILURE(
249 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(2000000)));
250
251 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(HWC_POWER_MODE_NORMAL));
252 ASSERT_NO_FATAL_FAILURE(
253 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000)));
254 ASSERT_NO_FATAL_FAILURE(
255 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000)));
256
257 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(HWC_POWER_MODE_OFF));
258 ASSERT_NO_FATAL_FAILURE(
259 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(6000000)));
260 ASSERT_NO_FATAL_FAILURE(
261 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(8000000)));
262
263 SFTimeStatsGlobalProto globalProto;
264 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
265
266 ASSERT_EQ(1, globalProto.present_to_present_size());
267 const SFTimeStatsHistogramBucketProto& histogramProto = globalProto.present_to_present().Get(0);
268 EXPECT_EQ(1, histogramProto.frame_count());
269 EXPECT_EQ(2, histogramProto.time_millis());
270}
271
272TEST_F(TimeStatsTest, canInsertOneLayerTimeStats) {
273 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
274
275 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
276 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 2, 2000000);
277
278 SFTimeStatsGlobalProto globalProto;
279 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
280
281 ASSERT_EQ(1, globalProto.stats_size());
282 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
283 ASSERT_TRUE(layerProto.has_layer_name());
284 EXPECT_EQ(genLayerName(LAYER_ID_0), layerProto.layer_name());
285 ASSERT_TRUE(layerProto.has_total_frames());
286 EXPECT_EQ(1, layerProto.total_frames());
287 ASSERT_EQ(6, layerProto.deltas_size());
288 for (const SFTimeStatsDeltaProto& deltaProto : layerProto.deltas()) {
289 ASSERT_EQ(1, deltaProto.histograms_size());
290 const SFTimeStatsHistogramBucketProto& histogramProto = deltaProto.histograms().Get(0);
291 EXPECT_EQ(1, histogramProto.frame_count());
292 if ("post2acquire" == deltaProto.delta_name()) {
293 EXPECT_EQ(1, histogramProto.time_millis());
294 } else if ("post2present" == deltaProto.delta_name()) {
295 EXPECT_EQ(4, histogramProto.time_millis());
296 } else if ("acquire2present" == deltaProto.delta_name()) {
297 EXPECT_EQ(3, histogramProto.time_millis());
298 } else if ("latch2present" == deltaProto.delta_name()) {
299 EXPECT_EQ(2, histogramProto.time_millis());
300 } else if ("desired2present" == deltaProto.delta_name()) {
301 EXPECT_EQ(1, histogramProto.time_millis());
302 } else if ("present2present" == deltaProto.delta_name()) {
303 EXPECT_EQ(1, histogramProto.time_millis());
304 } else {
305 FAIL() << "Unknown delta_name: " << deltaProto.delta_name();
306 }
307 }
308}
309
310TEST_F(TimeStatsTest, canNotInsertInvalidLayerNameTimeStats) {
311 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
312
313 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_INVALID, 1, 1000000);
314 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_INVALID, 2, 2000000);
315
316 SFTimeStatsGlobalProto globalProto;
317 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
318
319 ASSERT_EQ(0, globalProto.stats_size());
320}
321
322TEST_F(TimeStatsTest, canInsertMultipleLayersTimeStats) {
323 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
324
325 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
326 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 1000000);
327 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
328 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 2000000);
329
330 SFTimeStatsGlobalProto globalProto;
331 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
332
333 EXPECT_EQ(2, globalProto.stats_size());
334}
335
336TEST_F(TimeStatsTest, canInsertUnorderedLayerTimeStats) {
337 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
338
339 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
340 insertTimeRecord(UNORDERED_SEQUENCE, LAYER_ID_0, 2, 2000000);
341
342 SFTimeStatsGlobalProto globalProto;
343 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
344
345 ASSERT_EQ(1, globalProto.stats_size());
346 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
347 ASSERT_TRUE(layerProto.has_layer_name());
348 EXPECT_EQ(genLayerName(LAYER_ID_0), layerProto.layer_name());
349 ASSERT_TRUE(layerProto.has_total_frames());
350 EXPECT_EQ(1, layerProto.total_frames());
351 ASSERT_EQ(6, layerProto.deltas_size());
352 for (const SFTimeStatsDeltaProto& deltaProto : layerProto.deltas()) {
353 ASSERT_EQ(1, deltaProto.histograms_size());
354 const SFTimeStatsHistogramBucketProto& histogramProto = deltaProto.histograms().Get(0);
355 EXPECT_EQ(1, histogramProto.frame_count());
356 if ("post2acquire" == deltaProto.delta_name()) {
357 EXPECT_EQ(0, histogramProto.time_millis());
358 } else if ("post2present" == deltaProto.delta_name()) {
359 EXPECT_EQ(2, histogramProto.time_millis());
360 } else if ("acquire2present" == deltaProto.delta_name()) {
361 EXPECT_EQ(2, histogramProto.time_millis());
362 } else if ("latch2present" == deltaProto.delta_name()) {
363 EXPECT_EQ(2, histogramProto.time_millis());
364 } else if ("desired2present" == deltaProto.delta_name()) {
365 EXPECT_EQ(1, histogramProto.time_millis());
366 } else if ("present2present" == deltaProto.delta_name()) {
367 EXPECT_EQ(1, histogramProto.time_millis());
368 } else {
369 FAIL() << "Unknown delta_name: " << deltaProto.delta_name();
370 }
371 }
372}
373
374TEST_F(TimeStatsTest, canRemoveTimeRecord) {
375 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
376
377 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
378 insertTimeRecord(INCOMPLETE_SEQUENCE, LAYER_ID_0, 2, 2000000);
379 ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(0, 2));
380 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000);
381
382 SFTimeStatsGlobalProto globalProto;
383 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
384
385 ASSERT_EQ(1, globalProto.stats_size());
386 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
387 ASSERT_TRUE(layerProto.has_total_frames());
388 EXPECT_EQ(1, layerProto.total_frames());
389}
390
391TEST_F(TimeStatsTest, canRecoverFromIncompleteTimeRecordError) {
392 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
393
394 uint64_t frameNumber = 1;
395 nsecs_t ts = 1000000;
396 insertTimeRecord(INCOMPLETE_SEQUENCE, LAYER_ID_0, 1, 1000000);
397 for (size_t i = 0; i < TimeStats::MAX_NUM_TIME_RECORDS + 2; i++) {
398 frameNumber++;
399 ts += 1000000;
400 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, frameNumber, ts);
401 }
402
403 SFTimeStatsGlobalProto globalProto;
404 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
405
406 ASSERT_EQ(1, globalProto.stats_size());
407 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
408 ASSERT_TRUE(layerProto.has_total_frames());
409 EXPECT_EQ(1, layerProto.total_frames());
410}
411
412TEST_F(TimeStatsTest, layerTimeStatsOnDestroy) {
413 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
414
415 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
416 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
417 ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(0));
418 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000);
419
420 SFTimeStatsGlobalProto globalProto;
421 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
422
423 ASSERT_EQ(1, globalProto.stats_size());
424 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
425 ASSERT_TRUE(layerProto.has_total_frames());
426 EXPECT_EQ(1, layerProto.total_frames());
427}
428
429TEST_F(TimeStatsTest, canClearTimeStats) {
430 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
431
432 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementTotalFrames());
433 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames());
434 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionFrames());
435 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(HWC_POWER_MODE_NORMAL));
436 ASSERT_NO_FATAL_FAILURE(
437 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(1000000)));
438 ASSERT_NO_FATAL_FAILURE(
439 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(2000000)));
440 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
441 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
442
443 EXPECT_TRUE(inputCommand(InputCommand::CLEAR, FMT_STRING).empty());
444
445 SFTimeStatsGlobalProto globalProto;
446 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
447
448 EXPECT_EQ(0, globalProto.total_frames());
449 EXPECT_EQ(0, globalProto.missed_frames());
450 EXPECT_EQ(0, globalProto.client_composition_frames());
451 EXPECT_EQ(0, globalProto.present_to_present_size());
452 EXPECT_EQ(0, globalProto.stats_size());
453}
454
455TEST_F(TimeStatsTest, canDumpWithMaxLayers) {
456 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
457
458 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
459 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 1000000);
460 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
461 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 2000000);
462 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 3, 2000000);
463
464 SFTimeStatsGlobalProto globalProto;
465 ASSERT_TRUE(
466 globalProto.ParseFromString(inputCommand(InputCommand::DUMP_MAXLAYERS_1, FMT_PROTO)));
467
468 ASSERT_EQ(1, globalProto.stats_size());
469 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
470 ASSERT_TRUE(layerProto.has_layer_name());
471 EXPECT_EQ(genLayerName(LAYER_ID_1), layerProto.layer_name());
472 ASSERT_TRUE(layerProto.has_total_frames());
473 EXPECT_EQ(2, layerProto.total_frames());
474}
475
476TEST_F(TimeStatsTest, canDumpWithInvalidMaxLayers) {
477 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
478
479 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
480 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
481
482 SFTimeStatsGlobalProto globalProto;
483 ASSERT_TRUE(globalProto.ParseFromString(
484 inputCommand(InputCommand::DUMP_MAXLAYERS_INVALID, FMT_PROTO)));
485
486 ASSERT_EQ(0, globalProto.stats_size());
487}
488
489TEST_F(TimeStatsTest, canSurviveMonkey) {
Lloyd Pique067fe1e2018-12-06 19:44:13 -0800490 if (g_noSlowTests) {
491 GTEST_SKIP();
492 }
493
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800494 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
495
496 for (size_t i = 0; i < 10000000; ++i) {
497 const int32_t layerID = genRandomInt32(-1, 10);
498 const int32_t frameNumber = genRandomInt32(1, 10);
499 switch (genRandomInt32(0, 100)) {
500 case 0:
501 ALOGV("removeTimeRecord");
502 ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(layerID, frameNumber));
503 continue;
504 case 1:
505 ALOGV("onDestroy");
506 ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(layerID));
507 continue;
508 }
509 TimeStamp type = static_cast<TimeStamp>(genRandomInt32(TIME_STAMP_BEGIN, TIME_STAMP_END));
510 const int32_t ts = genRandomInt32(1, 1000000000);
511 ALOGV("type[%d], layerID[%d], frameNumber[%d], ts[%d]", type, layerID, frameNumber, ts);
512 setTimeStamp(type, layerID, frameNumber, ts);
513 }
514}
515
516} // namespace
517} // namespace android