File: pid_filter_pass.cpp

package info (click to toggle)
bpftrace 0.24.1-1.1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 10,496 kB
  • sloc: cpp: 60,982; ansic: 10,952; python: 953; yacc: 665; sh: 536; lex: 295; makefile: 22
file content (106 lines) | stat: -rw-r--r-- 2,594 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include "ast/passes/pid_filter_pass.h"
#include "ast/attachpoint_parser.h"
#include "ast/passes/field_analyser.h"
#include "ast/passes/printer.h"
#include "ast/passes/probe_expansion.h"
#include "driver.h"
#include "mocks.h"
#include "gtest/gtest.h"

namespace bpftrace::test::pid_filter_pass {

using ::testing::_;
using ::testing::HasSubstr;

void test(const std::string& input, bool has_pid, bool has_filter)
{
  auto mock_bpftrace = get_mock_bpftrace();
  BPFtrace& bpftrace = *mock_bpftrace;
  if (has_pid) {
    bpftrace.procmon_ = std::make_unique<MockProcMon>(1);
  }

  ast::ASTContext ast("stdin", input);
  std::stringstream msg;
  msg << "\nInput:\n" << input << "\n\nOutput:\n";

  // N.B. No macro or tracepoint expansion.
  auto ok = ast::PassManager()
                .put(ast)
                .put(bpftrace)
                .add(CreateParsePass())
                .add(ast::CreateParseAttachpointsPass())
                .add(ast::CreateProbeExpansionPass())
                .add(ast::CreateFieldAnalyserPass())
                .add(ast::CreatePidFilterPass())
                .run();
  ASSERT_TRUE(ok && ast.diagnostics().ok());

  std::string_view expected_ast = R"(
  if
   !=
    builtin: pid
    int: 1 :: [int64]
   then
    return
)";

  std::ostringstream out;
  ast::Printer printer(out);
  printer.visit(ast.root);

  if (has_filter) {
    EXPECT_THAT(out.str(), HasSubstr(expected_ast));
  } else {
    EXPECT_THAT(out.str(), Not(HasSubstr(expected_ast)));
  }
}

TEST(pid_filter_pass, add_filter)
{
  std::vector<std::string> filter_probes = {
    "kprobe:f",
    "kretprobe:f",
    "fentry:f",
    "fexit:f",
    "tracepoint:category:event",
    "rawtracepoint:module:event",
  };

  for (auto& probe : filter_probes) {
    test(probe + " { 1 }", true, true);
  }
}

TEST(pid_filter_pass, no_add_filter)
{
  // Sanity check: no pid, no filter
  test("kprobe:f { 1 }", false, false);
  test("profile:hz:99 { 1 }", false, false);

  std::vector<std::string> no_filter_probes = {
    "begin",
    "end",
    "uprobe:/bin/sh:f",
    "uretprobe:/bin/sh:f",
    "usdt:sh:probe",
    "watchpoint:0x0:8:rw",
    "asyncwatchpoint:func1+arg2:8:rw",
    "profile:ms:1",
    "interval:s:1",
    "software:faults:1000",
    "hardware:cache-references:1000000",
  };

  for (auto& probe : no_filter_probes) {
    test(probe + " { 1 }", true, false);
  }
}

TEST(pid_filter_pass, mixed_probes)
{
  test("kprobe:f, uprobe:/bin/sh:f { 1 }", true, true);
  test("usdt:sh:probe, uprobe:/bin/sh:f, profile:ms:1 { 1 }", true, false);
}

} // namespace bpftrace::test::pid_filter_pass