Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(366)

Side by Side Diff: base/process/process_metrics_unittest.cc

Issue 1526253003: Linux: Correctly count the number of open file descriptors. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: nit Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/process/process_metrics_linux.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « base/process/process_metrics_linux.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698