Honglin Yu | 1cd2507 | 2019-07-09 11:54:14 +1000 | [diff] [blame] | 1 | // Copyright 2019 The Chromium OS Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include <limits> |
| 6 | #include <string> |
| 7 | |
| 8 | #include <gmock/gmock.h> |
| 9 | #include <gtest/gtest.h> |
Qijiang Fan | 713061e | 2021-03-08 15:45:12 +0900 | [diff] [blame] | 10 | #include <base/check.h> |
Honglin Yu | 1cd2507 | 2019-07-09 11:54:14 +1000 | [diff] [blame] | 11 | #include <base/strings/string_number_conversions.h> |
| 12 | #include <base/strings/stringprintf.h> |
| 13 | #include <base/files/scoped_temp_dir.h> |
| 14 | #include <base/files/file_util.h> |
| 15 | #include <brillo/file_utils.h> |
| 16 | |
| 17 | #include "ml/test_utils.h" |
| 18 | #include "ml/util.h" |
| 19 | |
| 20 | namespace ml { |
| 21 | namespace { |
| 22 | |
| 23 | // Represents a temp status file valid for the lifetime of this object. |
| 24 | // The constructor creates a temp file named "status" in a temp folder and |
Andrew Moylan | 79b34a4 | 2020-07-08 11:13:11 +1000 | [diff] [blame] | 25 | // writes `content` to that file. |
Honglin Yu | 1cd2507 | 2019-07-09 11:54:14 +1000 | [diff] [blame] | 26 | // Use GetPath() to obtain the path fo the temporary file. |
| 27 | class ScopedTempStatusFile { |
| 28 | public: |
| 29 | explicit ScopedTempStatusFile(const std::string& content) { |
| 30 | CHECK(dir_.CreateUniqueTempDir()); |
| 31 | file_path_ = dir_.GetPath().Append("status"); |
| 32 | CHECK(brillo::WriteStringToFile(file_path_, content)); |
| 33 | } |
Qijiang Fan | 6bc59e1 | 2020-11-11 02:51:06 +0900 | [diff] [blame] | 34 | ScopedTempStatusFile(const ScopedTempStatusFile&) = delete; |
| 35 | ScopedTempStatusFile& operator=(const ScopedTempStatusFile&) = delete; |
| 36 | |
Honglin Yu | 1cd2507 | 2019-07-09 11:54:14 +1000 | [diff] [blame] | 37 | base::FilePath GetPath() { return file_path_; } |
| 38 | |
| 39 | private: |
| 40 | base::ScopedTempDir dir_; |
| 41 | base::FilePath file_path_; |
Honglin Yu | 1cd2507 | 2019-07-09 11:54:14 +1000 | [diff] [blame] | 42 | }; |
| 43 | |
| 44 | // Status file does not exist. |
| 45 | TEST(GetProcessMemoryUsageTest, InvalidFile) { |
| 46 | ScopedTempStatusFile status_file(""); |
| 47 | MemoryUsage memory_usage; |
| 48 | EXPECT_FALSE(GetProcessMemoryUsageFromFile( |
| 49 | &memory_usage, status_file.GetPath().Append("nonexistfile"))); |
| 50 | } |
| 51 | |
| 52 | TEST(GetProcessMemoryUsageTest, EmptyFile) { |
| 53 | ScopedTempStatusFile status_file(""); |
| 54 | MemoryUsage memory_usage; |
| 55 | EXPECT_FALSE( |
| 56 | GetProcessMemoryUsageFromFile(&memory_usage, status_file.GetPath())); |
| 57 | } |
| 58 | |
| 59 | TEST(GetProcessMemoryUsageTest, MissingVmSwap) { |
| 60 | ScopedTempStatusFile status_file("VmRSS: 3235 kB"); |
| 61 | MemoryUsage memory_usage; |
| 62 | EXPECT_FALSE( |
| 63 | GetProcessMemoryUsageFromFile(&memory_usage, status_file.GetPath())); |
| 64 | } |
| 65 | |
| 66 | TEST(GetProcessMemoryUsageTest, MissingVmRSS) { |
| 67 | ScopedTempStatusFile status_file("VmSwap: 34213 kB"); |
| 68 | MemoryUsage memory_usage; |
| 69 | EXPECT_FALSE( |
| 70 | GetProcessMemoryUsageFromFile(&memory_usage, status_file.GetPath())); |
| 71 | } |
| 72 | |
| 73 | TEST(GetProcessMemoryUsageTest, MissingBothValues) { |
| 74 | ScopedTempStatusFile status_file("VmRSS: kB \n VmSwap: kB\n"); |
| 75 | MemoryUsage memory_usage; |
| 76 | EXPECT_FALSE( |
| 77 | GetProcessMemoryUsageFromFile(&memory_usage, status_file.GetPath())); |
| 78 | } |
| 79 | |
| 80 | TEST(GetProcessMemoryUsageTest, MissingVmRSSValue) { |
| 81 | ScopedTempStatusFile status_file("VmRSS: kB \n VmSwap: 421532 kB\n"); |
| 82 | MemoryUsage memory_usage; |
| 83 | EXPECT_FALSE( |
| 84 | GetProcessMemoryUsageFromFile(&memory_usage, status_file.GetPath())); |
| 85 | } |
| 86 | |
| 87 | TEST(GetProcessMemoryUsageTest, MissingVmSwapValue) { |
| 88 | ScopedTempStatusFile status_file("VmRSS: 32432 kB \n VmSwap: kB\n"); |
| 89 | MemoryUsage memory_usage; |
| 90 | EXPECT_FALSE( |
| 91 | GetProcessMemoryUsageFromFile(&memory_usage, status_file.GetPath())); |
| 92 | } |
| 93 | |
| 94 | TEST(GetProcessMemoryUsageTest, InvalidVmSwapValueNan) { |
| 95 | ScopedTempStatusFile status_file( |
| 96 | "VmRSS: 767234322 kB \n VmSwap: nan kB\n"); |
| 97 | MemoryUsage memory_usage; |
| 98 | EXPECT_FALSE( |
| 99 | GetProcessMemoryUsageFromFile(&memory_usage, status_file.GetPath())); |
| 100 | } |
| 101 | |
| 102 | TEST(GetProcessMemoryUsageTest, InvalidVmRSSValueNan) { |
| 103 | ScopedTempStatusFile status_file("VmRSS: nan kB \n VmSwap: 4214 kB\n"); |
| 104 | MemoryUsage memory_usage; |
| 105 | EXPECT_FALSE( |
| 106 | GetProcessMemoryUsageFromFile(&memory_usage, status_file.GetPath())); |
| 107 | } |
| 108 | |
| 109 | TEST(GetProcessMemoryUsageTest, Duplicate) { |
| 110 | ScopedTempStatusFile status_file( |
| 111 | "VmRSS: 432 kB \n VmSwap: 421532 kB\n" |
| 112 | "VmRSS: 432 kB \n VmSwap: 421532 kB\n"); |
| 113 | MemoryUsage memory_usage; |
| 114 | EXPECT_FALSE( |
| 115 | GetProcessMemoryUsageFromFile(&memory_usage, status_file.GetPath())); |
| 116 | } |
| 117 | |
| 118 | TEST(GetProcessMemoryUsageTest, ValidInputNonZeroValue) { |
| 119 | ScopedTempStatusFile status_file("VmRSS: 432 kB \n VmSwap: 421532 kB\n"); |
| 120 | MemoryUsage memory_usage; |
| 121 | EXPECT_TRUE( |
| 122 | GetProcessMemoryUsageFromFile(&memory_usage, status_file.GetPath())); |
| 123 | EXPECT_EQ(memory_usage.VmRSSKb, 432); |
| 124 | EXPECT_EQ(memory_usage.VmSwapKb, 421532); |
| 125 | } |
| 126 | |
| 127 | TEST(GetProcessMemoryUsageTest, ValidInputZeroValue) { |
| 128 | ScopedTempStatusFile status_file("VmRSS: 0 kB \n VmSwap: 0 kB\n"); |
| 129 | MemoryUsage memory_usage; |
| 130 | EXPECT_TRUE( |
| 131 | GetProcessMemoryUsageFromFile(&memory_usage, status_file.GetPath())); |
| 132 | EXPECT_EQ(memory_usage.VmRSSKb, 0); |
| 133 | EXPECT_EQ(memory_usage.VmSwapKb, 0); |
| 134 | } |
| 135 | |
| 136 | TEST(GetProcessMemoryUsageTest, ValidInputZeroLead) { |
| 137 | ScopedTempStatusFile status_file( |
| 138 | "VmRSS: 0242 kB \n VmSwap: 03523 kB\n"); |
| 139 | MemoryUsage memory_usage; |
| 140 | EXPECT_TRUE( |
| 141 | GetProcessMemoryUsageFromFile(&memory_usage, status_file.GetPath())); |
| 142 | EXPECT_EQ(memory_usage.VmRSSKb, 242); |
| 143 | EXPECT_EQ(memory_usage.VmSwapKb, 3523); |
| 144 | } |
| 145 | |
| 146 | // Checks the maximum value of size_t. It may fail if treated as int32. |
| 147 | TEST(GetProcessMemoryUsageTest, ValidInputMaxSizeT) { |
| 148 | constexpr size_t kSizeTMax = std::numeric_limits<size_t>::max(); |
| 149 | |
| 150 | ScopedTempStatusFile status_file(base::StringPrintf( |
| 151 | "VmRSS: %zu kB\nVmSwap: %zu kB\n", kSizeTMax, kSizeTMax)); |
| 152 | MemoryUsage memory_usage; |
| 153 | EXPECT_TRUE( |
| 154 | GetProcessMemoryUsageFromFile(&memory_usage, status_file.GetPath())); |
| 155 | EXPECT_EQ(memory_usage.VmRSSKb, kSizeTMax); |
| 156 | EXPECT_EQ(memory_usage.VmSwapKb, kSizeTMax); |
| 157 | } |
| 158 | |
| 159 | TEST(GetProcessMemoryUsageTest, OrderChanged) { |
| 160 | ScopedTempStatusFile status_file( |
| 161 | "VmSwap: 34 kB\nVmRSS: 123 kB\n"); |
| 162 | MemoryUsage memory_usage; |
| 163 | EXPECT_TRUE( |
| 164 | GetProcessMemoryUsageFromFile(&memory_usage, status_file.GetPath())); |
| 165 | EXPECT_EQ(memory_usage.VmRSSKb, 123); |
| 166 | EXPECT_EQ(memory_usage.VmSwapKb, 34); |
| 167 | } |
| 168 | |
| 169 | TEST(GetProcessMemoryUsageTest, MissingNonMemoryValue) { |
| 170 | ScopedTempStatusFile status_file( |
| 171 | "VmSize: \nVmSwap: 34 kB\nVmRSS: 123 kB\n"); |
| 172 | MemoryUsage memory_usage; |
| 173 | EXPECT_TRUE( |
| 174 | GetProcessMemoryUsageFromFile(&memory_usage, status_file.GetPath())); |
| 175 | EXPECT_EQ(memory_usage.VmRSSKb, 123); |
| 176 | EXPECT_EQ(memory_usage.VmSwapKb, 34); |
| 177 | } |
| 178 | |
| 179 | TEST(GetProcessMemoryUsageTest, RealisticProcStatus) { |
| 180 | ScopedTempStatusFile status_file( |
| 181 | "Name: cat\n" |
| 182 | "Umask: 0022\n" |
| 183 | "State: R (running)\n" |
| 184 | "Tgid: 21255\n" |
| 185 | "Ngid: 0\n" |
| 186 | "Pid: 21255\n" |
| 187 | "PPid: 7\n" |
| 188 | "TracerPid: 0\n" |
| 189 | "Uid: 694971 694971 694971 694971\n" |
| 190 | "Gid: 89939 89939 89939 89939\n" |
| 191 | "FDSize: 256\n" |
| 192 | "Groups: 4 11 18 19 20 27 250 89939\n" |
| 193 | "NStgid: 21255\n" |
| 194 | "NSpid: 21255\n" |
| 195 | "NSpgid: 21255\n" |
| 196 | "NSsid: 0\n" |
| 197 | "VmPeak: 6048 kB\n" |
| 198 | "VmSize: 6048 kB\n" |
| 199 | "VmLck: 0 kB\n" |
| 200 | "VmPin: 0 kB\n" |
| 201 | "VmHWM: 732 kB\n" |
| 202 | "VmRSS: 732 kB\n" |
| 203 | "RssAnon: 68 kB\n" |
| 204 | "RssFile: 664 kB\n" |
| 205 | "RssShmem: 0 kB\n" |
| 206 | "VmData: 312 kB\n" |
| 207 | "VmStk: 136 kB\n" |
| 208 | "VmExe: 40 kB\n" |
| 209 | "VmLib: 1872 kB\n" |
| 210 | "VmPTE: 52 kB\n" |
| 211 | "VmSwap: 321 kB\n" |
| 212 | "HugetlbPages: 0 kB\n" |
| 213 | "CoreDumping: 0\n" |
| 214 | "Threads: 1\n" |
| 215 | "SigQ: 0/767737\n" |
| 216 | "SigPnd: 0000000000000000\n" |
| 217 | "ShdPnd: 0000000000000000\n" |
| 218 | "SigBlk: 0000000000000000\n" |
| 219 | "SigIgn: 0000000001001000\n" |
| 220 | "SigCgt: 0000000000000000\n" |
| 221 | "CapInh: 0000000000000000\n" |
| 222 | "CapPrm: 0000000000000000\n" |
| 223 | "CapEff: 0000000000000000\n" |
| 224 | "CapBnd: 0000003fffffffff\n" |
| 225 | "CapAmb: 0000000000000000\n" |
| 226 | "NoNewPrivs: 0\n" |
| 227 | "Seccomp: 0\n" |
| 228 | "Speculation_Store_Bypass: thread vulnerable\n" |
| 229 | "Cpus_allowed: ff,ffffffff,ffffffff\n" |
| 230 | "Cpus_allowed_list: 0-71\n" |
| 231 | "Mems_allowed: 00000000,00000003\n" |
| 232 | "Mems_allowed_list: 0-1\n" |
| 233 | "voluntary_ctxt_switches: 0\n" |
| 234 | "nonvoluntary_ctxt_switches: 1\n"); |
| 235 | MemoryUsage memory_usage; |
| 236 | EXPECT_TRUE( |
| 237 | GetProcessMemoryUsageFromFile(&memory_usage, status_file.GetPath())); |
| 238 | EXPECT_EQ(memory_usage.VmRSSKb, 732); |
| 239 | EXPECT_EQ(memory_usage.VmSwapKb, 321); |
| 240 | } |
| 241 | |
| 242 | } // namespace |
| 243 | } // namespace ml |