1 /*
2  * Copyright (C) 2020 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 #include "src/profiling/common/profiler_guardrails.h"
18 
19 #include <inttypes.h>
20 #include <unistd.h>
21 
22 #include <map>
23 
24 #include "perfetto/ext/base/file_utils.h"
25 #include "perfetto/ext/base/optional.h"
26 #include "perfetto/ext/base/temp_file.h"
27 #include "test/gtest_and_gmock.h"
28 
29 namespace perfetto {
30 namespace profiling {
31 namespace {
32 
TEST(ProfilerCpuGuardrailsTest,Exceeded)33 TEST(ProfilerCpuGuardrailsTest, Exceeded) {
34   const auto clk = static_cast<unsigned long>(sysconf(_SC_CLK_TCK));
35   base::TempFile f = base::TempFile::CreateUnlinked();
36   constexpr const char stat[] =
37       "2965981 (zsh) S 2965977 2965981 2965981 34822 2966607 4194304 6632 6697 "
38       "0 0 1000000 6000000 4 1 20 0 1 0 227163466 15839232 2311 "
39       "18446744073709551615 "
40       "94823961161728 94823961762781 140722993535472 0 0 0 2 3686400 134295555 "
41       "0 0 0 17 2 0 0 0 0 0 94823961905904 94823961935208 94823993954304 "
42       "140722993543678 140722993543691 140722993543691 140722993545195 0";
43   base::WriteAll(f.fd(), stat, sizeof(stat));
44   ASSERT_NE(lseek(f.fd(), 0, SEEK_SET), -1);
45   ProfilerCpuGuardrails gr(f.ReleaseFD());
46 
47   GuardrailConfig gc;
48   gc.cpu_guardrail_sec = 5000000 / clk;
49   gc.cpu_start_secs = 1000000 / clk;
50   EXPECT_TRUE(gr.IsOverCpuThreshold(gc));
51 }
52 
TEST(ProfilerCpuGuardrailsTest,NotExceeded)53 TEST(ProfilerCpuGuardrailsTest, NotExceeded) {
54   const auto clk = static_cast<unsigned long>(sysconf(_SC_CLK_TCK));
55   base::TempFile f = base::TempFile::CreateUnlinked();
56   constexpr const char stat[] =
57       "2965981 (zsh) S 2965977 2965981 2965981 34822 2966607 4194304 6632 6697 "
58       "0 0 1000000 6000000 4 1 20 0 1 0 227163466 15839232 2311 "
59       "18446744073709551615 "
60       "94823961161728 94823961762781 140722993535472 0 0 0 2 3686400 134295555 "
61       "0 0 0 17 2 0 0 0 0 0 94823961905904 94823961935208 94823993954304 "
62       "140722993543678 140722993543691 140722993543691 140722993545195 0";
63   base::WriteAll(f.fd(), stat, sizeof(stat));
64   ASSERT_NE(lseek(f.fd(), 0, SEEK_SET), -1);
65   ProfilerCpuGuardrails gr(f.ReleaseFD());
66 
67   GuardrailConfig gc;
68   gc.cpu_guardrail_sec = 7000000 / clk;
69   gc.cpu_start_secs = 1000000 / clk;
70   EXPECT_FALSE(gr.IsOverCpuThreshold(gc));
71 }
72 
TEST(ProfilerMemoryGuardrailsTest,Exceeded)73 TEST(ProfilerMemoryGuardrailsTest, Exceeded) {
74   base::TempFile f = base::TempFile::CreateUnlinked();
75   constexpr const char status[] =
76       "VmPeak:\t    5432 kB\n"
77       "VmSize:\t    5432 kB\n"
78       "VmLck:\t       0 kB\n"
79       "VmPin:\t       0 kB\n"
80       "VmHWM:\t     584 kB\n"
81       "VmRSS:\t     80 kB\n"
82       "RssAnon:\t      68 kB\n"
83       "RssFile:\t     516 kB\n"
84       "RssShmem:\t       0 kB\n"
85       "VmData:\t     316 kB\n"
86       "VmStk:\t     132 kB\n"
87       "VmExe:\t      20 kB\n"
88       "VmLib:\t    1460 kB\n"
89       "VmPTE:\t      44 kB\n"
90       "VmSwap:\t       10 kB\n";
91 
92   base::WriteAll(f.fd(), status, sizeof(status));
93   ASSERT_NE(lseek(f.fd(), 0, SEEK_SET), -1);
94   ProfilerMemoryGuardrails gr(f.ReleaseFD());
95 
96   GuardrailConfig gc;
97   gc.memory_guardrail_kb = 77;
98   EXPECT_TRUE(gr.IsOverMemoryThreshold(gc));
99 }
100 
TEST(ProfilerMemoryGuardrailsTest,NotExceeded)101 TEST(ProfilerMemoryGuardrailsTest, NotExceeded) {
102   base::TempFile f = base::TempFile::CreateUnlinked();
103   constexpr const char status[] =
104       "VmPeak:\t    5432 kB\n"
105       "VmSize:\t    5432 kB\n"
106       "VmLck:\t       0 kB\n"
107       "VmPin:\t       0 kB\n"
108       "VmHWM:\t     584 kB\n"
109       "VmRSS:\t     80 kB\n"
110       "RssAnon:\t      68 kB\n"
111       "RssFile:\t     516 kB\n"
112       "RssShmem:\t       0 kB\n"
113       "VmData:\t     316 kB\n"
114       "VmStk:\t     132 kB\n"
115       "VmExe:\t      20 kB\n"
116       "VmLib:\t    1460 kB\n"
117       "VmPTE:\t      44 kB\n"
118       "VmSwap:\t       10 kB\n";
119 
120   base::WriteAll(f.fd(), status, sizeof(status));
121   ASSERT_NE(lseek(f.fd(), 0, SEEK_SET), -1);
122   ProfilerMemoryGuardrails gr(f.ReleaseFD());
123   GuardrailConfig gc;
124   gc.memory_guardrail_kb = 100;
125   EXPECT_FALSE(gr.IsOverMemoryThreshold(gc));
126 }
127 
128 }  // namespace
129 }  // namespace profiling
130 }  // namespace perfetto
131