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