blob: 76b615af79b858c0caa834f35d35f6bde9561460 [file] [log] [blame]
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "src/profiling/perf/perf_producer.h"
#include <stdint.h>
#include <optional>
#include "perfetto/base/logging.h"
#include "test/gtest_and_gmock.h"
namespace perfetto {
namespace profiling {
namespace {
bool ShouldReject(pid_t pid,
std::string cmdline,
const TargetFilter& filter,
bool skip_cmd,
base::FlatSet<std::string>* additional_cmdlines) {
return PerfProducer::ShouldRejectDueToFilter(
pid, filter, skip_cmd, additional_cmdlines, [cmdline](std::string* out) {
*out = cmdline;
return true;
});
}
TEST(TargetFilterTest, EmptyFilter) {
{
bool skip_cmd = false;
base::FlatSet<std::string> extra_cmds;
TargetFilter filter;
// empty filter allows everything
EXPECT_FALSE(ShouldReject(42, "/bin/echo", filter, skip_cmd, &extra_cmds));
EXPECT_FALSE(ShouldReject(77, "/bin/echo", filter, skip_cmd, &extra_cmds));
}
{
bool skip_cmd = false;
base::FlatSet<std::string> extra_cmds;
TargetFilter filter;
filter.exclude_pids.insert(1);
// allow everything besides the explicit exclusions
EXPECT_FALSE(ShouldReject(42, "/bin/echo", filter, skip_cmd, &extra_cmds));
EXPECT_FALSE(ShouldReject(77, "/bin/echo", filter, skip_cmd, &extra_cmds));
EXPECT_TRUE(ShouldReject(1, "/sbin/init", filter, skip_cmd, &extra_cmds));
}
}
TEST(TargetFilterTest, TargetPids) {
bool skip_cmd = false;
base::FlatSet<std::string> extra_cmds;
TargetFilter filter;
filter.pids.insert(32);
filter.pids.insert(42);
EXPECT_FALSE(ShouldReject(32, "/bin/echo", filter, skip_cmd, &extra_cmds));
EXPECT_FALSE(ShouldReject(42, "/bin/echo", filter, skip_cmd, &extra_cmds));
EXPECT_TRUE(ShouldReject(77, "/bin/echo", filter, skip_cmd, &extra_cmds));
}
TEST(TargetFilterTest, ExcludePids) {
bool skip_cmd = false;
base::FlatSet<std::string> extra_cmds;
TargetFilter filter;
filter.exclude_pids.insert(32);
filter.exclude_pids.insert(42);
EXPECT_FALSE(ShouldReject(77, "/bin/echo", filter, skip_cmd, &extra_cmds));
EXPECT_TRUE(ShouldReject(32, "/bin/echo", filter, skip_cmd, &extra_cmds));
EXPECT_TRUE(ShouldReject(42, "/bin/echo", filter, skip_cmd, &extra_cmds));
}
TEST(TargetFilterTest, TargetCmdlines) {
{
bool skip_cmd = false;
base::FlatSet<std::string> extra_cmds;
TargetFilter filter;
filter.cmdlines.emplace_back("echo");
filter.cmdlines.emplace_back("/bin/cat");
EXPECT_FALSE(ShouldReject(42, "/bin/echo", filter, skip_cmd, &extra_cmds));
EXPECT_FALSE(ShouldReject(42, "/bin/cat", filter, skip_cmd, &extra_cmds));
EXPECT_TRUE(ShouldReject(42, "/bin/top", filter, skip_cmd, &extra_cmds));
}
{
bool skip_cmd = true;
base::FlatSet<std::string> extra_cmds;
TargetFilter filter;
filter.cmdlines.emplace_back("echo");
filter.cmdlines.emplace_back("/bin/cat");
// As above but with |skip_cmd| making none of the cmdline checks apply.
// Therefore everything gets rejected because it's still considered to be a
// filter that only requested specific targets (and none of these match).
EXPECT_TRUE(ShouldReject(42, "/bin/echo", filter, skip_cmd, &extra_cmds));
EXPECT_TRUE(ShouldReject(42, "/bin/cat", filter, skip_cmd, &extra_cmds));
EXPECT_TRUE(ShouldReject(42, "/bin/top", filter, skip_cmd, &extra_cmds));
}
}
TEST(TargetFilterTest, ExcludeCmdlines) {
bool skip_cmd = false;
base::FlatSet<std::string> extra_cmds;
TargetFilter filter;
filter.exclude_cmdlines.emplace_back("echo");
filter.exclude_cmdlines.emplace_back("/bin/cat");
EXPECT_FALSE(ShouldReject(42, "/bin/top", filter, skip_cmd, &extra_cmds));
EXPECT_TRUE(ShouldReject(42, "/bin/echo", filter, skip_cmd, &extra_cmds));
EXPECT_TRUE(ShouldReject(42, "/bin/cat", filter, skip_cmd, &extra_cmds));
}
TEST(TargetFilterTest, ExclusionPrioritised) {
bool skip_cmd = false;
base::FlatSet<std::string> extra_cmds;
TargetFilter filter;
filter.pids.insert(42);
filter.exclude_pids.insert(42);
filter.cmdlines.push_back("echo");
filter.exclude_cmdlines.push_back("echo");
EXPECT_TRUE(ShouldReject(42, "/bin/cat", filter, skip_cmd, &extra_cmds));
EXPECT_TRUE(ShouldReject(100, "/bin/echo", filter, skip_cmd, &extra_cmds));
}
TEST(TargetFilterTest, ProcessSharding) {
{
bool skip_cmd = false;
base::FlatSet<std::string> extra_cmds;
TargetFilter filter;
filter.process_sharding =
ProcessSharding{/*shard_count=*/4, /*chosen_shard=*/1};
EXPECT_FALSE(ShouldReject(1, "/bin/echo", filter, skip_cmd, &extra_cmds));
EXPECT_FALSE(ShouldReject(41, "/bin/echo", filter, skip_cmd, &extra_cmds));
EXPECT_TRUE(ShouldReject(0, "/bin/echo", filter, skip_cmd, &extra_cmds));
EXPECT_TRUE(ShouldReject(42, "/bin/echo", filter, skip_cmd, &extra_cmds));
}
{
// as above but with an explicit exclude_pid
bool skip_cmd = false;
base::FlatSet<std::string> extra_cmds;
TargetFilter filter;
filter.exclude_pids.insert(41);
filter.process_sharding =
ProcessSharding{/*shard_count=*/4, /*chosen_shard=*/1};
EXPECT_FALSE(ShouldReject(1, "/bin/echo", filter, skip_cmd, &extra_cmds));
// explicit exclusion applies even if pid is in the accepted shard
EXPECT_TRUE(ShouldReject(41, "/bin/echo", filter, skip_cmd, &extra_cmds));
EXPECT_TRUE(ShouldReject(42, "/bin/echo", filter, skip_cmd, &extra_cmds));
}
}
TEST(TargetFilterTest, AdditionalCmdlines) {
bool skip_cmd = false;
base::FlatSet<std::string> extra_cmds;
TargetFilter filter;
filter.additional_cmdline_count = 2;
// first two distinct cmdlines remembered and allowed:
EXPECT_FALSE(ShouldReject(42, "/bin/echo", filter, skip_cmd, &extra_cmds));
EXPECT_FALSE(ShouldReject(43, "/bin/echo", filter, skip_cmd, &extra_cmds));
EXPECT_FALSE(ShouldReject(44, "/bin/cat", filter, skip_cmd, &extra_cmds));
// further cmdlines rejected:
EXPECT_TRUE(ShouldReject(45, "/bin/top", filter, skip_cmd, &extra_cmds));
// remembered cmdlines still allowed:
EXPECT_FALSE(ShouldReject(46, "/bin/echo", filter, skip_cmd, &extra_cmds));
EXPECT_EQ(extra_cmds.size(), 2u);
EXPECT_EQ(extra_cmds.count("/bin/echo"), 1u);
EXPECT_EQ(extra_cmds.count("/bin/cat"), 1u);
EXPECT_EQ(extra_cmds.count("/bin/top"), 0u);
}
} // namespace
} // namespace profiling
} // namespace perfetto