// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/metrics/perf/process_type_collector.h"
#include <stdint.h>
#include "base/test/metrics/histogram_tester.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace metrics {
namespace {
void GetExampleProcessTypeDataset(std::string* ps_output,
std::map<uint32_t, Process>* process_types,
std::vector<uint32_t>* lacros_pids,
std::string* lacros_path) {
*ps_output = R"(PID CMD
1000 /opt/google/chrome/chrome --type=
1500 /opt/google/chrome/chrome --type= --some-flag
2000 /opt/google/chrome/chrome --type=renderer --enable-logging
3000 /opt/google/chrome/chrome --type=gpu-process
4000 /opt/google/chrome/chrome --log-level=1 --type=utility
5000 /opt/google/chrome/chrome --type=zygote
6000 /opt/google/chrome/chrome --type=ppapi
7100 /opt/google/chrome/chrome --type=random-type
7200 /opt/google/chrome/chrome --no_type
11000 /run/lacros/chrome --ozone-platform=wayland
12000 /run/lacros/chrome --type=renderer --enable-logging
13000 /run/lacros/chrome --type=gpu-process
14000 /run/lacros/chrome --log-level=1 --type=utility
15000 /run/lacros/chrome --type=zygote
21000 /run/imageloader/lacros-dogfood-dev/95.0.4623.2/chrome
22000 /run/imageloader/lacros-dogfood-dev/95.0.4623.2/chrome )"
R"(--type=renderer --enable-logging
23000 /run/imageloader/lacros-dogfood-dev/95.0.4623.2/chrome )"
R"(--type=gpu-process
24000 /run/imageloader/lacros-dogfood-dev/95.0.4623.2/chrome )"
R"(--log-level=1 --type=utility
25000 /run/imageloader/lacros-dogfood-dev/95.0.4623.2/chrome --type=zygote
129000 /opt/google/chrome/chrome --ppapi-flash-path=..../libpepflashplayer.so"
180000 [kswapd0])";
process_types->insert(std::pair(1000, Process::BROWSER_PROCESS));
process_types->insert(std::pair(1500, Process::BROWSER_PROCESS));
process_types->insert(std::pair(2000, Process::RENDERER_PROCESS));
process_types->insert(std::pair(3000, Process::GPU_PROCESS));
process_types->insert(std::pair(4000, Process::UTILITY_PROCESS));
process_types->insert(std::pair(5000, Process::ZYGOTE_PROCESS));
process_types->insert(std::pair(6000, Process::PPAPI_PLUGIN_PROCESS));
process_types->insert(std::pair(7100, Process::OTHER_PROCESS));
process_types->insert(std::pair(7200, Process::BROWSER_PROCESS));
process_types->insert(std::pair(129000, Process::BROWSER_PROCESS));
process_types->insert(std::pair(11000, Process::BROWSER_PROCESS));
process_types->insert(std::pair(12000, Process::RENDERER_PROCESS));
process_types->insert(std::pair(13000, Process::GPU_PROCESS));
process_types->insert(std::pair(14000, Process::UTILITY_PROCESS));
process_types->insert(std::pair(15000, Process::ZYGOTE_PROCESS));
process_types->insert(std::pair(21000, Process::BROWSER_PROCESS));
process_types->insert(std::pair(22000, Process::RENDERER_PROCESS));
process_types->insert(std::pair(23000, Process::GPU_PROCESS));
process_types->insert(std::pair(24000, Process::UTILITY_PROCESS));
process_types->insert(std::pair(25000, Process::ZYGOTE_PROCESS));
lacros_pids->emplace_back(11000);
lacros_pids->emplace_back(12000);
lacros_pids->emplace_back(13000);
lacros_pids->emplace_back(14000);
lacros_pids->emplace_back(15000);
lacros_pids->emplace_back(21000);
lacros_pids->emplace_back(22000);
lacros_pids->emplace_back(23000);
lacros_pids->emplace_back(24000);
lacros_pids->emplace_back(25000);
*lacros_path = "/run/lacros/chrome";
}
void GetExampleThreadTypeDataset(std::string* ps_output,
std::map<uint32_t, Thread>* thread_types) {
*ps_output =
R"( PID LWP COMMAND CMD
1 1 init /sbin/init
12000 12000 chrome /opt/google/chrome/chrome --ppapi-flash-path=...
3000 1107 irq/5-E:<L0000> [irq/5-E:<L0000>]
4000 4726 Chrome_IOThread /opt/google/chrome/chrome --ppapi-flash-path=...
7274 7495 AudioOutputDevi /opt/google/chrome/chrome --type=renderer
10000 12107 Chrome_ChildIOT /opt/google/chrome/chrome --type=gpu-process
11000 12207 VizCompositorTh /opt/google/chrome/chrome --type=gpu-process
12103 12112 Compositor/7 /opt/google/chrome/chrome --type=gpu-process
12304 12699 Compositor /opt/google/chrome/chrome --type=gpu-process
13001 13521 GpuMemoryThread /opt/google/chrome/chrome --type=renderer
15000 15112 ThreadPoolForeg /opt/google/chrome/chrome --type=renderer
16000 16112 CompositorTileW /opt/google/chrome/chrome --type=renderer
17001 17021 MemoryInfra /opt/google/chrome/chrome --type=renderer
18020 18211 Media /opt/google/chrome/chrome --type=renderer
18887 19060 dav1d-worker /opt/google/chrome/chrome --type=renderer
19001 19008 DedicatedWorker /opt/google/chrome/chrome --type=renderer
19123 19234 ServiceWorker t /opt/google/chrome/chrome --type=renderer
19321 19335 WebRTC_Signalin /opt/google/chrome/chrome --type=renderer
19321 19336 StackSamplingPr /opt/google/chrome/chrome --type=renderer
19321 19337 VideoFrameCompo /opt/google/chrome/chrome --type=renderer
19321 19338 CodecWorker /opt/google/chrome/chrome --type=renderer
19321 19345 DrmThread /opt/google/chrome/chrome --type=gpu-process
19390 19428 AudioThread /opt/google/chrome/chrome
12345 12456 OtherThread /opt/google/chrome/chrome --ppapi-flash-path=...
21609 21609 chrome /run/lacros/chrome --ozone-platform=wayland
21643 21667 ThreadPoolServi /run/lacros/chrome --type=gpu-process
21643 21669 Chrome_ChildIOT /run/lacros/chrome --type=gpu-process
21643 21671 VizCompositorTh /run/lacros/chrome --type=gpu-process
21707 21713 GpuMemoryThread /run/lacros/chrome --type=renderer
21707 21718 CompositorTileW /run/lacros/chrome --type=renderer
21707 23600 MemoryInfra /run/lacros/chrome --type=renderer
21737 21784 WebRTC_Network /run/lacros/chrome --type=renderer
31609 31609 chrome )"
R"(/run/imageloader/lacros-dogfood-dev/95.0.4623.2/chrome
31643 31668 ThreadPoolForeg )"
R"(/run/imageloader/lacros-dogfood-dev/95.0.4623.2/chrome )"
R"(--type=gpu-process
31725 31732 Compositor )"
R"(/run/imageloader/lacros-dogfood-dev/95.0.4623.2/chrome --type=renderer
31737 31783 WebRTC_Signalin )"
R"(/run/imageloader/lacros-dogfood-dev/95.0.4623.2/chrome --type=renderer
31737 31785 Media )"
R"(/run/imageloader/lacros-dogfood-dev/95.0.4623.2/chrome --type=renderer
31737 31790 DedicatedWorker )"
R"(/run/imageloader/lacros-dogfood-dev/95.0.4623.2/chrome --type=renderer
31814 34416 ServiceWorker t )"
R"(/run/imageloader/lacros-dogfood-dev/95.0.4623.2/chrome --type=renderer
13456 13566 Compositor/6 non_chrome_exec --some-flag=foo)";
thread_types->insert(std::pair(12000, Thread::MAIN_THREAD));
thread_types->insert(std::pair(4726, Thread::IO_THREAD));
thread_types->insert(std::pair(7495, Thread::AUDIO_DEVICE_THREAD));
thread_types->insert(std::pair(12107, Thread::IO_THREAD));
thread_types->insert(std::pair(12207, Thread::COMPOSITOR_THREAD));
thread_types->insert(std::pair(12112, Thread::COMPOSITOR_THREAD));
thread_types->insert(std::pair(12699, Thread::COMPOSITOR_THREAD));
thread_types->insert(std::pair(15112, Thread::THREAD_POOL_THREAD));
thread_types->insert(std::pair(13521, Thread::GPU_MEMORY_THREAD));
thread_types->insert(std::pair(16112, Thread::COMPOSITOR_TILE_WORKER_THREAD));
thread_types->insert(std::pair(17021, Thread::MEMORY_INFRA_THREAD));
thread_types->insert(std::pair(18211, Thread::MEDIA_THREAD));
thread_types->insert(std::pair(19008, Thread::DEDICATED_WORKER_THREAD));
thread_types->insert(std::pair(19060, Thread::DAV1D_WORKER_THREAD));
thread_types->insert(std::pair(19234, Thread::SERVICE_WORKER_THREAD));
thread_types->insert(std::pair(19335, Thread::WEBRTC_THREAD));
thread_types->insert(std::pair(19336, Thread::STACK_SAMPLING_THREAD));
thread_types->insert(std::pair(19337, Thread::VIDEO_FRAME_COMPOSITOR_THREAD));
thread_types->insert(std::pair(19338, Thread::CODEC_WORKER_THREAD));
thread_types->insert(std::pair(19345, Thread::DRM_THREAD));
thread_types->insert(std::pair(19428, Thread::AUDIO_THREAD));
thread_types->insert(std::pair(12456, Thread::OTHER_THREAD));
thread_types->insert(std::pair(21609, Thread::MAIN_THREAD));
thread_types->insert(std::pair(21667, Thread::THREAD_POOL_THREAD));
thread_types->insert(std::pair(21669, Thread::IO_THREAD));
thread_types->insert(std::pair(21671, Thread::COMPOSITOR_THREAD));
thread_types->insert(std::pair(21713, Thread::GPU_MEMORY_THREAD));
thread_types->insert(std::pair(21718, Thread::COMPOSITOR_TILE_WORKER_THREAD));
thread_types->insert(std::pair(23600, Thread::MEMORY_INFRA_THREAD));
thread_types->insert(std::pair(21784, Thread::WEBRTC_THREAD));
thread_types->insert(std::pair(31609, Thread::MAIN_THREAD));
thread_types->insert(std::pair(31668, Thread::THREAD_POOL_THREAD));
thread_types->insert(std::pair(31732, Thread::COMPOSITOR_THREAD));
thread_types->insert(std::pair(31783, Thread::WEBRTC_THREAD));
thread_types->insert(std::pair(31785, Thread::MEDIA_THREAD));
thread_types->insert(std::pair(31790, Thread::DEDICATED_WORKER_THREAD));
thread_types->insert(std::pair(34416, Thread::SERVICE_WORKER_THREAD));
}
class TestProcessTypeCollector : public ProcessTypeCollector {
public:
using ProcessTypeCollector::CollectionAttemptStatus;
using ProcessTypeCollector::ParseProcessTypes;
using ProcessTypeCollector::ParseThreadTypes;
TestProcessTypeCollector(const TestProcessTypeCollector&) = delete;
TestProcessTypeCollector& operator=(const TestProcessTypeCollector&) = delete;
};
} // namespace
TEST(ProcessTypeCollectorTest, ValidProcessTypeInput) {
std::map<uint32_t, Process> want_process_types;
std::string input;
std::vector<uint32_t> want_lacros_pids;
std::string want_lacros_path;
GetExampleProcessTypeDataset(&input, &want_process_types, &want_lacros_pids,
&want_lacros_path);
EXPECT_FALSE(input.empty());
EXPECT_FALSE(want_process_types.empty());
EXPECT_FALSE(want_lacros_pids.empty());
EXPECT_FALSE(want_lacros_path.empty());
base::HistogramTester histogram_tester;
std::vector<uint32_t> got_lacros_pids;
std::string got_lacros_path;
std::map<uint32_t, Process> got_process_types =
TestProcessTypeCollector::ParseProcessTypes(input, got_lacros_pids,
got_lacros_path);
histogram_tester.ExpectBucketCount(
"ChromeOS.CWP.CollectProcessTypes",
TestProcessTypeCollector::CollectionAttemptStatus::kProcessTypeSuccess,
1);
EXPECT_EQ(got_process_types, want_process_types);
EXPECT_EQ(got_lacros_pids, want_lacros_pids);
EXPECT_EQ(got_lacros_path, want_lacros_path);
}
TEST(ProcessTypeCollectorTest, ProcessTypeInputWithCorruptedLine) {
std::string input = R"text(PPID CMD COMMAND
PID /opt/google/chrome/chrome --type=
1000 /opt/google/chrome/chrome --type=
PID /run/lacros/chrome --type=
2000 /run/lacros/chrome --type=)text";
std::map<uint32_t, Process> want_process_types;
want_process_types.emplace(1000, Process::BROWSER_PROCESS);
want_process_types.emplace(2000, Process::BROWSER_PROCESS);
std::vector<uint32_t> want_lacros_pids(1, 2000);
std::string want_lacros_path = "/run/lacros/chrome";
base::HistogramTester histogram_tester;
std::vector<uint32_t> got_lacros_pids;
std::string got_lacros_path;
std::map<uint32_t, Process> got_process_types =
TestProcessTypeCollector::ParseProcessTypes(input, got_lacros_pids,
got_lacros_path);
histogram_tester.ExpectBucketCount(
"ChromeOS.CWP.CollectProcessTypes",
TestProcessTypeCollector::CollectionAttemptStatus::kProcessTypeTruncated,
1);
EXPECT_EQ(got_process_types, want_process_types);
EXPECT_EQ(got_lacros_pids, want_lacros_pids);
EXPECT_FALSE(got_lacros_path.empty());
EXPECT_EQ(got_lacros_path, want_lacros_path);
}
TEST(ProcessTypeCollectorTest, ProcessTypeInputWithDuplicatePIDs) {
std::string input = R"text(PID CMD
1000 /opt/google/chrome/chrome --type=
1000 /opt/google/chrome/chrome --type=
2000 /run/lacros/chrome --type=
2000 /run/lacros/chrome --type=)text";
std::map<uint32_t, Process> want_process_types;
want_process_types.emplace(1000, Process::BROWSER_PROCESS);
want_process_types.emplace(2000, Process::BROWSER_PROCESS);
std::vector<uint32_t> want_lacros_pids(1, 2000);
std::string want_lacros_path = "/run/lacros/chrome";
base::HistogramTester histogram_tester;
std::vector<uint32_t> got_lacros_pids;
std::string got_lacros_path;
std::map<uint32_t, Process> got_process_types =
TestProcessTypeCollector::ParseProcessTypes(input, got_lacros_pids,
got_lacros_path);
histogram_tester.ExpectBucketCount(
"ChromeOS.CWP.CollectProcessTypes",
TestProcessTypeCollector::CollectionAttemptStatus::kProcessTypeTruncated,
1);
EXPECT_EQ(got_process_types, want_process_types);
EXPECT_EQ(got_lacros_pids, want_lacros_pids);
EXPECT_FALSE(got_lacros_path.empty());
EXPECT_EQ(got_lacros_path, want_lacros_path);
}
TEST(ProcessTypeCollectorTest, ProcessTypeInputWithEmptyLine) {
std::string input = R"text(PPID CMD COMMAND
1000 /opt/google/chrome/chrome --type=
)text";
std::map<uint32_t, Process> want_process_types;
std::vector<uint32_t> want_lacros_pids;
want_process_types.emplace(1000, Process::BROWSER_PROCESS);
base::HistogramTester histogram_tester;
std::vector<uint32_t> got_lacros_pids;
std::string got_lacros_path;
std::map<uint32_t, Process> got_process_types =
TestProcessTypeCollector::ParseProcessTypes(input, got_lacros_pids,
got_lacros_path);
histogram_tester.ExpectBucketCount(
"ChromeOS.CWP.CollectProcessTypes",
TestProcessTypeCollector::CollectionAttemptStatus::kProcessTypeTruncated,
1);
EXPECT_EQ(got_process_types, want_process_types);
EXPECT_EQ(got_lacros_pids, want_lacros_pids);
EXPECT_TRUE(got_lacros_path.empty());
}
TEST(ProcessTypeCollectorTest, ValidThreadTypeInput) {
std::map<uint32_t, Thread> want_thread_types;
std::string input;
GetExampleThreadTypeDataset(&input, &want_thread_types);
EXPECT_FALSE(input.empty());
EXPECT_FALSE(want_thread_types.empty());
base::HistogramTester histogram_tester;
std::map<uint32_t, Thread> got_thread_types =
TestProcessTypeCollector::ParseThreadTypes(input);
histogram_tester.ExpectBucketCount(
"ChromeOS.CWP.CollectProcessTypes",
TestProcessTypeCollector::CollectionAttemptStatus::kThreadTypeSuccess, 1);
EXPECT_EQ(got_thread_types, want_thread_types);
}
TEST(ProcessTypeCollectorTest, ThreadTypeInputWithCorruptedLine) {
std::string input = R"text( PID LWPCMD
PID LWP init
4000 4726 Chrome_IOThread /opt/google/chrome/chrome --ppapi-flash=...)text";
std::map<uint32_t, Thread> want_thread_types;
want_thread_types.emplace(4726, Thread::IO_THREAD);
base::HistogramTester histogram_tester;
std::map<uint32_t, Thread> got_thread_types =
TestProcessTypeCollector::ParseThreadTypes(input);
histogram_tester.ExpectBucketCount(
"ChromeOS.CWP.CollectProcessTypes",
TestProcessTypeCollector::CollectionAttemptStatus::kThreadTypeTruncated,
1);
EXPECT_EQ(got_thread_types, want_thread_types);
}
TEST(ProcessTypeCollectorTest, ThreadTypeInputWithDuplicateTIDs) {
std::string input = R"text( PID LWP CMD
4000 4726 Chrome_IOThread /opt/google/chrome/chrome --ppapi-flash-path=...
4000 4726 VizCompositorTh /opt/google/chrome/chrome --type=gpu-process)text";
std::map<uint32_t, Thread> want_thread_types;
want_thread_types.emplace(4726, Thread::IO_THREAD);
base::HistogramTester histogram_tester;
std::map<uint32_t, Thread> got_thread_types =
TestProcessTypeCollector::ParseThreadTypes(input);
histogram_tester.ExpectBucketCount(
"ChromeOS.CWP.CollectProcessTypes",
TestProcessTypeCollector::CollectionAttemptStatus::kThreadTypeTruncated,
1);
EXPECT_EQ(got_thread_types, want_thread_types);
}
TEST(ProcessTypeCollectorTest, ThreadTypeInputWithEmptyLine) {
std::string input = R"text( PID LWPCMD
4000 4726 Chrome_IOThread /opt/google/chrome/chrome --ppapi-flash=...
)text";
std::map<uint32_t, Thread> want_thread_types;
want_thread_types.emplace(4726, Thread::IO_THREAD);
base::HistogramTester histogram_tester;
std::map<uint32_t, Thread> got_thread_types =
TestProcessTypeCollector::ParseThreadTypes(input);
histogram_tester.ExpectBucketCount(
"ChromeOS.CWP.CollectProcessTypes",
TestProcessTypeCollector::CollectionAttemptStatus::kThreadTypeTruncated,
1);
EXPECT_EQ(got_thread_types, want_thread_types);
}
} // namespace metrics