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