blob: 1113f425a80b8c94a617e358e6bae524cf0ed493 [file] [log] [blame]
Connor O'Briencd0e5c62016-12-15 16:32:01 -08001/*
2 * Copyright (C) 2016 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#define LOG_TAG "memtrack_hidl_hal_test"
18#include <android-base/logging.h>
19#include <android/hardware/memtrack/1.0/IMemtrack.h>
20
Yuexi Ma50d7e272017-02-28 01:46:51 -080021#include <VtsHalHidlTargetBaseTest.h>
Connor O'Briencd0e5c62016-12-15 16:32:01 -080022
23#include <algorithm>
24#include <vector>
25
26using ::android::hardware::memtrack::V1_0::IMemtrack;
27using ::android::hardware::memtrack::V1_0::MemtrackRecord;
28using ::android::hardware::memtrack::V1_0::MemtrackFlag;
29using ::android::hardware::memtrack::V1_0::MemtrackType;
30using ::android::hardware::memtrack::V1_0::MemtrackStatus;
31using ::android::hardware::hidl_vec;
32using ::android::hardware::Return;
33using ::android::sp;
34using std::vector;
35using std::count_if;
36
Yuexi Ma50d7e272017-02-28 01:46:51 -080037class MemtrackHidlTest : public ::testing::VtsHalHidlTargetBaseTest {
Connor O'Briencd0e5c62016-12-15 16:32:01 -080038 public:
39 virtual void SetUp() override {
Yuexi Ma50d7e272017-02-28 01:46:51 -080040 memtrack = ::testing::VtsHalHidlTargetBaseTest::getService<IMemtrack>();
Connor O'Briencd0e5c62016-12-15 16:32:01 -080041 ASSERT_NE(memtrack, nullptr);
42 }
43
44 virtual void TearDown() override {}
45
46 sp<IMemtrack> memtrack;
47};
48
49/* Returns true if flags contains at least min, and no more than max,
50 * of the flags in flagSet. Returns false otherwise.
51 */
52bool rightFlagCount(uint32_t flags, vector<MemtrackFlag> flagSet, uint32_t min,
53 uint32_t max) {
54 uint32_t count =
55 count_if(flagSet.begin(), flagSet.end(),
56 [&](MemtrackFlag f) { return flags & (uint32_t)f; });
57 return (min <= count && count <= max);
58}
59
60/* Returns true when passed a valid, defined status, false otherwise.
61 */
62bool validStatus(MemtrackStatus s) {
63 vector<MemtrackStatus> statusVec = {
64 MemtrackStatus::SUCCESS, MemtrackStatus::MEMORY_TRACKING_NOT_SUPPORTED,
65 MemtrackStatus::TYPE_NOT_SUPPORTED};
66 return std::find(statusVec.begin(), statusVec.end(), s) != statusVec.end();
67}
68
69/* Returns a pid found in /proc for which the string read from
70 * /proc/[pid]/cmdline matches cmd, or -1 if no such pid exists.
71 */
72pid_t getPidFromCmd(const char cmd[], uint32_t len) {
73 const char procs[] = "/proc/";
74 DIR *dir = opendir(procs);
75 if (!dir) {
76 return -1;
77 }
78
79 struct dirent *proc;
80 while ((proc = readdir(dir)) != NULL) {
81 if (!isdigit(proc->d_name[0])) {
82 continue;
83 }
84 char line[len];
85 char fname[PATH_MAX];
86 snprintf(fname, PATH_MAX, "/proc/%s/cmdline", proc->d_name);
87
88 FILE *file = fopen(fname, "r");
89 if (!file) {
90 continue;
91 }
92 char *str = fgets(line, len, file);
93 fclose(file);
94 if (!str || strcmp(str, cmd)) {
95 continue;
96 } else {
97 closedir(dir);
98 return atoi(proc->d_name);
99 }
100 }
101 closedir(dir);
102 return -1;
103}
104
105auto generate_cb(MemtrackStatus *s, hidl_vec<MemtrackRecord> *v) {
106 return [=](MemtrackStatus status, hidl_vec<MemtrackRecord> vec) {
107 *s = status;
108 *v = vec;
109 };
110}
111
112/* Sanity check results when getMemory() is passed a negative PID
113 */
114TEST_F(MemtrackHidlTest, BadPidTest) {
115 MemtrackStatus s;
116 hidl_vec<MemtrackRecord> v;
117 auto cb = generate_cb(&s, &v);
118 for (uint32_t i = 0; i < static_cast<uint32_t>(MemtrackType::NUM_TYPES);
119 i++) {
120 Return<void> ret =
121 memtrack->getMemory(-1, static_cast<MemtrackType>(i), cb);
122 ASSERT_TRUE(ret.isOk());
123 ASSERT_TRUE(validStatus(s));
124 }
125}
126
127/* Sanity check results when getMemory() is passed a bad memory usage type
128 */
129TEST_F(MemtrackHidlTest, BadTypeTest) {
130 MemtrackStatus s;
131 hidl_vec<MemtrackRecord> v;
132 auto cb = generate_cb(&s, &v);
133 Return<void> ret = memtrack->getMemory(getpid(), MemtrackType::NUM_TYPES, cb);
134 ASSERT_TRUE(ret.isOk());
135 ASSERT_TRUE(validStatus(s));
136}
137
138/* Call memtrack on the surfaceflinger process and check that the results are
139 * reasonable for all memory types, including valid flag combinations for
140 * every MemtrackRecord returned.
141 */
142TEST_F(MemtrackHidlTest, SurfaceflingerTest) {
143 const char cmd[] = "/system/bin/surfaceflinger";
144 const uint32_t len = sizeof(cmd);
145 pid_t pid = getPidFromCmd(cmd, len);
146 ASSERT_LE(0, pid) << "Surfaceflinger process not found";
147
148 MemtrackStatus s;
149 hidl_vec<MemtrackRecord> v;
150 auto cb = generate_cb(&s, &v);
151 uint32_t unsupportedCount = 0;
152 for (uint32_t i = 0; i < static_cast<uint32_t>(MemtrackType::NUM_TYPES);
153 i++) {
154 Return<void> ret =
155 memtrack->getMemory(pid, static_cast<MemtrackType>(i), cb);
156 ASSERT_TRUE(ret.isOk());
157
158 switch (s) {
159 case MemtrackStatus::MEMORY_TRACKING_NOT_SUPPORTED:
160 unsupportedCount++;
161 break;
162 case MemtrackStatus::TYPE_NOT_SUPPORTED:
163 break;
164 case MemtrackStatus::SUCCESS: {
165 for (uint32_t j = 0; j < v.size(); j++) {
166 // Enforce flag constraints
167 vector<MemtrackFlag> smapFlags = {MemtrackFlag::SMAPS_ACCOUNTED,
168 MemtrackFlag::SMAPS_UNACCOUNTED};
169 EXPECT_TRUE(rightFlagCount(v[j].flags, smapFlags, 1, 1));
170 vector<MemtrackFlag> shareFlags = {MemtrackFlag::SHARED,
171 MemtrackFlag::SHARED_PSS,
172 MemtrackFlag::PRIVATE};
173 EXPECT_TRUE(rightFlagCount(v[j].flags, shareFlags, 0, 1));
174 vector<MemtrackFlag> systemFlags = {MemtrackFlag::SYSTEM,
175 MemtrackFlag::DEDICATED};
176 EXPECT_TRUE(rightFlagCount(v[j].flags, systemFlags, 0, 1));
177 vector<MemtrackFlag> secureFlags = {MemtrackFlag::SECURE,
178 MemtrackFlag::NONSECURE};
179 EXPECT_TRUE(rightFlagCount(v[j].flags, secureFlags, 0, 1));
180 }
181 break;
182 }
183 default:
184 FAIL();
185 }
186 }
187 // If tracking is not supported this should be returned for all types.
188 ASSERT_TRUE(unsupportedCount == 0 ||
189 unsupportedCount ==
190 static_cast<uint32_t>(MemtrackType::NUM_TYPES));
191}
192
193int main(int argc, char **argv) {
194 ::testing::InitGoogleTest(&argc, argv);
195 int status = RUN_ALL_TESTS();
196 LOG(INFO) << "Test result = " << status;
197 return status;
198}