OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/process/process_metrics.h" | 5 #include "base/process/process_metrics.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/command_line.h" |
| 12 #include "base/files/file.h" |
| 13 #include "base/files/file_util.h" |
| 14 #include "base/files/scoped_temp_dir.h" |
11 #include "base/strings/string_number_conversions.h" | 15 #include "base/strings/string_number_conversions.h" |
| 16 #include "base/test/multiprocess_test.h" |
12 #include "base/threading/thread.h" | 17 #include "base/threading/thread.h" |
13 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
14 | 19 #include "testing/multiprocess_func_list.h" |
15 | 20 |
16 namespace base { | 21 namespace base { |
17 namespace debug { | 22 namespace debug { |
18 | 23 |
19 #if defined(OS_LINUX) || defined(OS_CHROMEOS) | 24 #if defined(OS_LINUX) || defined(OS_CHROMEOS) |
20 namespace { | 25 namespace { |
21 | 26 |
22 void BusyWork(std::vector<std::string>* vec) { | 27 void BusyWork(std::vector<std::string>* vec) { |
23 int64_t test_value = 0; | 28 int64_t test_value = 0; |
24 for (int i = 0; i < 100000; ++i) { | 29 for (int i = 0; i < 100000; ++i) { |
25 ++test_value; | 30 ++test_value; |
26 vec->push_back(base::Int64ToString(test_value)); | 31 vec->push_back(Int64ToString(test_value)); |
27 } | 32 } |
28 } | 33 } |
29 | 34 |
30 } // namespace | 35 } // namespace |
31 #endif // defined(OS_LINUX) || defined(OS_CHROMEOS) | 36 #endif // defined(OS_LINUX) || defined(OS_CHROMEOS) |
32 | 37 |
33 // Tests for SystemMetrics. | 38 // Tests for SystemMetrics. |
34 // Exists as a class so it can be a friend of SystemMetrics. | 39 // Exists as a class so it can be a friend of SystemMetrics. |
35 class SystemMetricsTest : public testing::Test { | 40 class SystemMetricsTest : public testing::Test { |
36 public: | 41 public: |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 EXPECT_EQ(meminfo.pgmajfault, 2023); | 290 EXPECT_EQ(meminfo.pgmajfault, 2023); |
286 } | 291 } |
287 #endif // defined(OS_LINUX) || defined(OS_ANDROID) | 292 #endif // defined(OS_LINUX) || defined(OS_ANDROID) |
288 | 293 |
289 #if defined(OS_LINUX) || defined(OS_CHROMEOS) | 294 #if defined(OS_LINUX) || defined(OS_CHROMEOS) |
290 | 295 |
291 // Test that ProcessMetrics::GetCPUUsage() doesn't return negative values when | 296 // Test that ProcessMetrics::GetCPUUsage() doesn't return negative values when |
292 // the number of threads running on the process decreases between two successive | 297 // the number of threads running on the process decreases between two successive |
293 // calls to it. | 298 // calls to it. |
294 TEST_F(SystemMetricsTest, TestNoNegativeCpuUsage) { | 299 TEST_F(SystemMetricsTest, TestNoNegativeCpuUsage) { |
295 base::ProcessHandle handle = base::GetCurrentProcessHandle(); | 300 ProcessHandle handle = GetCurrentProcessHandle(); |
296 scoped_ptr<ProcessMetrics> metrics( | 301 scoped_ptr<ProcessMetrics> metrics( |
297 ProcessMetrics::CreateProcessMetrics(handle)); | 302 ProcessMetrics::CreateProcessMetrics(handle)); |
298 | 303 |
299 EXPECT_GE(metrics->GetCPUUsage(), 0.0); | 304 EXPECT_GE(metrics->GetCPUUsage(), 0.0); |
300 Thread thread1("thread1"); | 305 Thread thread1("thread1"); |
301 Thread thread2("thread2"); | 306 Thread thread2("thread2"); |
302 Thread thread3("thread3"); | 307 Thread thread3("thread3"); |
303 | 308 |
304 thread1.StartAndWaitForTesting(); | 309 thread1.StartAndWaitForTesting(); |
305 thread2.StartAndWaitForTesting(); | 310 thread2.StartAndWaitForTesting(); |
306 thread3.StartAndWaitForTesting(); | 311 thread3.StartAndWaitForTesting(); |
307 | 312 |
308 ASSERT_TRUE(thread1.IsRunning()); | 313 ASSERT_TRUE(thread1.IsRunning()); |
309 ASSERT_TRUE(thread2.IsRunning()); | 314 ASSERT_TRUE(thread2.IsRunning()); |
310 ASSERT_TRUE(thread3.IsRunning()); | 315 ASSERT_TRUE(thread3.IsRunning()); |
311 | 316 |
312 std::vector<std::string> vec1; | 317 std::vector<std::string> vec1; |
313 std::vector<std::string> vec2; | 318 std::vector<std::string> vec2; |
314 std::vector<std::string> vec3; | 319 std::vector<std::string> vec3; |
315 | 320 |
316 thread1.task_runner()->PostTask(FROM_HERE, base::Bind(&BusyWork, &vec1)); | 321 thread1.task_runner()->PostTask(FROM_HERE, Bind(&BusyWork, &vec1)); |
317 thread2.task_runner()->PostTask(FROM_HERE, base::Bind(&BusyWork, &vec2)); | 322 thread2.task_runner()->PostTask(FROM_HERE, Bind(&BusyWork, &vec2)); |
318 thread3.task_runner()->PostTask(FROM_HERE, base::Bind(&BusyWork, &vec3)); | 323 thread3.task_runner()->PostTask(FROM_HERE, Bind(&BusyWork, &vec3)); |
319 | 324 |
320 EXPECT_GE(metrics->GetCPUUsage(), 0.0); | 325 EXPECT_GE(metrics->GetCPUUsage(), 0.0); |
321 | 326 |
322 thread1.Stop(); | 327 thread1.Stop(); |
323 EXPECT_GE(metrics->GetCPUUsage(), 0.0); | 328 EXPECT_GE(metrics->GetCPUUsage(), 0.0); |
324 | 329 |
325 thread2.Stop(); | 330 thread2.Stop(); |
326 EXPECT_GE(metrics->GetCPUUsage(), 0.0); | 331 EXPECT_GE(metrics->GetCPUUsage(), 0.0); |
327 | 332 |
328 thread3.Stop(); | 333 thread3.Stop(); |
329 EXPECT_GE(metrics->GetCPUUsage(), 0.0); | 334 EXPECT_GE(metrics->GetCPUUsage(), 0.0); |
330 } | 335 } |
331 | 336 |
332 #endif // defined(OS_LINUX) || defined(OS_CHROMEOS) | 337 #endif // defined(OS_LINUX) || defined(OS_CHROMEOS) |
333 | 338 |
334 #if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) || \ | 339 #if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) || \ |
335 defined(OS_LINUX) || defined(OS_ANDROID) | 340 defined(OS_LINUX) || defined(OS_ANDROID) |
336 TEST(SystemMetrics2Test, GetSystemMemoryInfo) { | 341 TEST(SystemMetrics2Test, GetSystemMemoryInfo) { |
337 base::SystemMemoryInfoKB info; | 342 SystemMemoryInfoKB info; |
338 EXPECT_TRUE(base::GetSystemMemoryInfo(&info)); | 343 EXPECT_TRUE(GetSystemMemoryInfo(&info)); |
339 | 344 |
340 // Ensure each field received a value. | 345 // Ensure each field received a value. |
341 EXPECT_GT(info.total, 0); | 346 EXPECT_GT(info.total, 0); |
342 EXPECT_GT(info.free, 0); | 347 EXPECT_GT(info.free, 0); |
343 #if defined(OS_LINUX) || defined(OS_ANDROID) | 348 #if defined(OS_LINUX) || defined(OS_ANDROID) |
344 EXPECT_GT(info.buffers, 0); | 349 EXPECT_GT(info.buffers, 0); |
345 EXPECT_GT(info.cached, 0); | 350 EXPECT_GT(info.cached, 0); |
346 EXPECT_GT(info.active_anon, 0); | 351 EXPECT_GT(info.active_anon, 0); |
347 EXPECT_GT(info.inactive_anon, 0); | 352 EXPECT_GT(info.inactive_anon, 0); |
348 EXPECT_GT(info.active_file, 0); | 353 EXPECT_GT(info.active_file, 0); |
(...skipping 24 matching lines...) Expand all Loading... |
373 | 378 |
374 #if defined(OS_LINUX) || defined(OS_ANDROID) | 379 #if defined(OS_LINUX) || defined(OS_ANDROID) |
375 TEST(ProcessMetricsTest, ParseProcStatCPU) { | 380 TEST(ProcessMetricsTest, ParseProcStatCPU) { |
376 // /proc/self/stat for a process running "top". | 381 // /proc/self/stat for a process running "top". |
377 const char kTopStat[] = "960 (top) S 16230 960 16230 34818 960 " | 382 const char kTopStat[] = "960 (top) S 16230 960 16230 34818 960 " |
378 "4202496 471 0 0 0 " | 383 "4202496 471 0 0 0 " |
379 "12 16 0 0 " // <- These are the goods. | 384 "12 16 0 0 " // <- These are the goods. |
380 "20 0 1 0 121946157 15077376 314 18446744073709551615 4194304 " | 385 "20 0 1 0 121946157 15077376 314 18446744073709551615 4194304 " |
381 "4246868 140733983044336 18446744073709551615 140244213071219 " | 386 "4246868 140733983044336 18446744073709551615 140244213071219 " |
382 "0 0 0 138047495 0 0 0 17 1 0 0 0 0 0"; | 387 "0 0 0 138047495 0 0 0 17 1 0 0 0 0 0"; |
383 EXPECT_EQ(12 + 16, base::ParseProcStatCPU(kTopStat)); | 388 EXPECT_EQ(12 + 16, ParseProcStatCPU(kTopStat)); |
384 | 389 |
385 // cat /proc/self/stat on a random other machine I have. | 390 // cat /proc/self/stat on a random other machine I have. |
386 const char kSelfStat[] = "5364 (cat) R 5354 5364 5354 34819 5364 " | 391 const char kSelfStat[] = "5364 (cat) R 5354 5364 5354 34819 5364 " |
387 "0 142 0 0 0 " | 392 "0 142 0 0 0 " |
388 "0 0 0 0 " // <- No CPU, apparently. | 393 "0 0 0 0 " // <- No CPU, apparently. |
389 "16 0 1 0 1676099790 2957312 114 4294967295 134512640 134528148 " | 394 "16 0 1 0 1676099790 2957312 114 4294967295 134512640 134528148 " |
390 "3221224832 3221224344 3086339742 0 0 0 0 0 0 0 17 0 0 0"; | 395 "3221224832 3221224344 3086339742 0 0 0 0 0 0 0 17 0 0 0"; |
391 | 396 |
392 EXPECT_EQ(0, base::ParseProcStatCPU(kSelfStat)); | 397 EXPECT_EQ(0, ParseProcStatCPU(kSelfStat)); |
393 | 398 |
394 // Some weird long-running process with a weird name that I created for the | 399 // Some weird long-running process with a weird name that I created for the |
395 // purposes of this test. | 400 // purposes of this test. |
396 const char kWeirdNameStat[] = "26115 (Hello) You ())) ) R 24614 26115 24614" | 401 const char kWeirdNameStat[] = "26115 (Hello) You ())) ) R 24614 26115 24614" |
397 " 34839 26115 4218880 227 0 0 0 " | 402 " 34839 26115 4218880 227 0 0 0 " |
398 "5186 11 0 0 " | 403 "5186 11 0 0 " |
399 "20 0 1 0 36933953 4296704 90 18446744073709551615 4194304 4196116 " | 404 "20 0 1 0 36933953 4296704 90 18446744073709551615 4194304 4196116 " |
400 "140735857761568 140735857761160 4195644 0 0 0 0 0 0 0 17 14 0 0 0 0 0 " | 405 "140735857761568 140735857761160 4195644 0 0 0 0 0 0 0 17 14 0 0 0 0 0 " |
401 "6295056 6295616 16519168 140735857770710 140735857770737 " | 406 "6295056 6295616 16519168 140735857770710 140735857770737 " |
402 "140735857770737 140735857774557 0"; | 407 "140735857770737 140735857774557 0"; |
403 EXPECT_EQ(5186 + 11, base::ParseProcStatCPU(kWeirdNameStat)); | 408 EXPECT_EQ(5186 + 11, ParseProcStatCPU(kWeirdNameStat)); |
404 } | 409 } |
405 #endif // defined(OS_LINUX) || defined(OS_ANDROID) | 410 #endif // defined(OS_LINUX) || defined(OS_ANDROID) |
406 | 411 |
407 // Disable on Android because base_unittests runs inside a Dalvik VM that | 412 // Disable on Android because base_unittests runs inside a Dalvik VM that |
408 // starts and stop threads (crbug.com/175563). | 413 // starts and stop threads (crbug.com/175563). |
409 #if defined(OS_LINUX) | 414 #if defined(OS_LINUX) |
410 // http://crbug.com/396455 | 415 // http://crbug.com/396455 |
411 TEST(ProcessMetricsTest, DISABLED_GetNumberOfThreads) { | 416 TEST(ProcessMetricsTest, DISABLED_GetNumberOfThreads) { |
412 const base::ProcessHandle current = base::GetCurrentProcessHandle(); | 417 const ProcessHandle current = GetCurrentProcessHandle(); |
413 const int initial_threads = base::GetNumberOfThreads(current); | 418 const int initial_threads = GetNumberOfThreads(current); |
414 ASSERT_GT(initial_threads, 0); | 419 ASSERT_GT(initial_threads, 0); |
415 const int kNumAdditionalThreads = 10; | 420 const int kNumAdditionalThreads = 10; |
416 { | 421 { |
417 scoped_ptr<base::Thread> my_threads[kNumAdditionalThreads]; | 422 scoped_ptr<Thread> my_threads[kNumAdditionalThreads]; |
418 for (int i = 0; i < kNumAdditionalThreads; ++i) { | 423 for (int i = 0; i < kNumAdditionalThreads; ++i) { |
419 my_threads[i].reset(new base::Thread("GetNumberOfThreadsTest")); | 424 my_threads[i].reset(new Thread("GetNumberOfThreadsTest")); |
420 my_threads[i]->Start(); | 425 my_threads[i]->Start(); |
421 ASSERT_EQ(base::GetNumberOfThreads(current), initial_threads + 1 + i); | 426 ASSERT_EQ(GetNumberOfThreads(current), initial_threads + 1 + i); |
422 } | 427 } |
423 } | 428 } |
424 // The Thread destructor will stop them. | 429 // The Thread destructor will stop them. |
425 ASSERT_EQ(initial_threads, base::GetNumberOfThreads(current)); | 430 ASSERT_EQ(initial_threads, GetNumberOfThreads(current)); |
426 } | 431 } |
427 #endif // defined(OS_LINUX) | 432 #endif // defined(OS_LINUX) |
428 | 433 |
| 434 #if defined(OS_LINUX) |
| 435 namespace { |
| 436 |
| 437 // Keep these in sync so the GetOpenFdCount test can refer to correct test main. |
| 438 #define ChildMain ChildFdCount |
| 439 #define ChildMainString "ChildFdCount" |
| 440 |
| 441 // Command line flag name and file name used for synchronization. |
| 442 const char kTempDirFlag[] = "temp-dir"; |
| 443 const char kSignalClosed[] = "closed"; |
| 444 |
| 445 bool SignalEvent(const FilePath& signal_dir, const char* signal_file) { |
| 446 File file(signal_dir.AppendASCII(signal_file), |
| 447 File::FLAG_CREATE | File::FLAG_WRITE); |
| 448 return file.IsValid(); |
| 449 } |
| 450 |
| 451 // Check whether an event was signaled. |
| 452 bool CheckEvent(const FilePath& signal_dir, const char* signal_file) { |
| 453 File file(signal_dir.AppendASCII(signal_file), |
| 454 File::FLAG_OPEN | File::FLAG_READ); |
| 455 return file.IsValid(); |
| 456 } |
| 457 |
| 458 // Busy-wait for an event to be signaled. |
| 459 void WaitForEvent(const FilePath& signal_dir, const char* signal_file) { |
| 460 while (!CheckEvent(signal_dir, signal_file)) |
| 461 PlatformThread::Sleep(TimeDelta::FromMilliseconds(10)); |
| 462 } |
| 463 |
| 464 // Subprocess to test the number of open file descriptors. |
| 465 MULTIPROCESS_TEST_MAIN(ChildMain) { |
| 466 CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| 467 const FilePath temp_path = command_line->GetSwitchValuePath(kTempDirFlag); |
| 468 CHECK(DirectoryExists(temp_path)); |
| 469 |
| 470 // Try to close all the file descriptors, so the open count goes to 0. |
| 471 for (size_t i = 0; i < 1000; ++i) |
| 472 close(i); |
| 473 CHECK(SignalEvent(temp_path, kSignalClosed)); |
| 474 |
| 475 // Wait to be terminated. |
| 476 while (true) |
| 477 PlatformThread::Sleep(TimeDelta::FromSeconds(1)); |
| 478 return 0; |
| 479 } |
| 480 |
| 481 } // namespace |
| 482 |
| 483 TEST(ProcessMetricsTest, GetOpenFdCount) { |
| 484 ScopedTempDir temp_dir; |
| 485 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 486 const FilePath temp_path = temp_dir.path(); |
| 487 CommandLine child_command_line(GetMultiProcessTestChildBaseCommandLine()); |
| 488 child_command_line.AppendSwitchPath(kTempDirFlag, temp_path); |
| 489 Process child = SpawnMultiProcessTestChild( |
| 490 ChildMainString, child_command_line, LaunchOptions()); |
| 491 ASSERT_TRUE(child.IsValid()); |
| 492 WaitForEvent(temp_path, kSignalClosed); |
| 493 |
| 494 scoped_ptr<ProcessMetrics> metrics( |
| 495 ProcessMetrics::CreateProcessMetrics(child.Handle())); |
| 496 EXPECT_EQ(0, metrics->GetOpenFdCount()); |
| 497 ASSERT_TRUE(child.Terminate(0, true)); |
| 498 } |
| 499 #endif // defined(OS_LINUX) |
| 500 |
429 } // namespace debug | 501 } // namespace debug |
430 } // namespace base | 502 } // namespace base |
OLD | NEW |