1 //===- FileLineColLocBreakpointManagerTest.cpp - --------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "mlir/Debug/BreakpointManagers/FileLineColLocBreakpointManager.h"
10 #include "mlir/Debug/ExecutionContext.h"
11 #include "mlir/IR/Builders.h"
12 #include "mlir/IR/BuiltinAttributes.h"
13 #include "mlir/IR/BuiltinTypes.h"
14 #include "mlir/IR/Location.h"
15 #include "mlir/IR/OperationSupport.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "gtest/gtest.h"
20 using namespace mlir::tracing
;
22 static Operation
*createOp(MLIRContext
*context
, Location loc
,
23 StringRef operationName
,
24 unsigned int numRegions
= 0) {
25 context
->allowUnregisteredDialects();
26 return Operation::create(loc
, OperationName(operationName
, context
),
27 std::nullopt
, std::nullopt
, std::nullopt
,
28 OpaqueProperties(nullptr), std::nullopt
, numRegions
);
32 struct FileLineColLocTestingAction
33 : public ActionImpl
<FileLineColLocTestingAction
> {
34 MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(FileLineColLocTestingAction
)
35 static constexpr StringLiteral tag
= "file-line-col-loc-testing-action";
36 FileLineColLocTestingAction(ArrayRef
<IRUnit
> irUnits
)
37 : ActionImpl
<FileLineColLocTestingAction
>(irUnits
) {}
40 TEST(FileLineColLocBreakpointManager
, OperationMatch
) {
41 // This test will process a sequence of operation and check various situation
42 // with a breakpoint hitting or not based on the location attached to the
43 // operation. When a breakpoint hits, the action is skipped and the counter is
45 ExecutionContext
executionCtx(
46 [](const ActionActiveStack
*) { return ExecutionContext::Skip
; });
48 auto counterInc
= [&]() { counter
++; };
53 // Miscellaneous information to define operations
54 std::vector
<StringRef
> fileNames
= {
55 StringRef("foo.bar"), StringRef("baz.qux"), StringRef("quux.corge")};
56 std::vector
<std::pair
<unsigned, unsigned>> lineColLoc
= {{42, 7}, {24, 3}};
57 Location callee
= UnknownLoc::get(&context
),
58 caller
= UnknownLoc::get(&context
), loc
= UnknownLoc::get(&context
);
60 // Set of operations over where we are going to be testing the functionality
61 std::vector
<Operation
*> operations
= {
62 createOp(&context
, CallSiteLoc::get(callee
, caller
),
63 "callSiteLocOperation"),
65 FileLineColLoc::get(&context
, fileNames
[0], lineColLoc
[0].first
,
66 lineColLoc
[0].second
),
67 "fileLineColLocOperation"),
68 createOp(&context
, FusedLoc::get(&context
, {}, Attribute()),
70 createOp(&context
, NameLoc::get(StringAttr::get(&context
, fileNames
[2])),
72 createOp(&context
, OpaqueLoc::get
<void *>(nullptr, loc
),
73 "opaqueLocOperation"),
75 FileLineColLoc::get(&context
, fileNames
[1], lineColLoc
[1].first
,
76 lineColLoc
[1].second
),
77 "anotherFileLineColLocOperation"),
78 createOp(&context
, UnknownLoc::get(&context
), "unknownLocOperation"),
81 FileLineColLocBreakpointManager breakpointManager
;
82 executionCtx
.addBreakpointManager(&breakpointManager
);
86 // Basic case is that no breakpoint is set and the counter is incremented for
88 auto checkNoMatch
= [&]() {
90 for (auto enumeratedOp
: llvm::enumerate(operations
)) {
91 executionCtx(counterInc
,
92 FileLineColLocTestingAction({enumeratedOp
.value()}));
93 EXPECT_EQ(counter
, static_cast<int>(enumeratedOp
.index() + 1));
98 // Set a breakpoint matching only the second operation in the list.
99 auto *breakpoint
= breakpointManager
.addBreakpoint(
100 fileNames
[0], lineColLoc
[0].first
, lineColLoc
[0].second
);
101 auto checkMatchIdxs
= [&](DenseSet
<int> idxs
) {
104 for (int i
= 0; i
< (int)operations
.size(); ++i
) {
105 executionCtx(counterInc
, FileLineColLocTestingAction({operations
[i
]}));
106 if (!idxs
.contains(i
))
108 EXPECT_EQ(counter
, reference
);
113 // Check that disabling the breakpoing brings us back to the original
115 breakpoint
->disable();
118 // Adding a breakpoint that won't match any location shouldn't affect the
120 breakpointManager
.addBreakpoint(StringRef("random.file"), 3, 14);
123 // Set a breakpoint matching only the fifth operation in the list.
124 breakpointManager
.addBreakpoint(fileNames
[1], lineColLoc
[1].first
,
125 lineColLoc
[1].second
);
129 // Re-enable the breakpoint matching only the second operation in the list.
130 // We now expect matching of operations 1 and 5.
131 breakpoint
->enable();
132 checkMatchIdxs({1, 5});
134 for (auto *op
: operations
) {
139 TEST(FileLineColLocBreakpointManager
, BlockMatch
) {
140 // This test will process a block and check various situation with
141 // a breakpoint hitting or not based on the location attached.
142 // When a breakpoint hits, the action is skipped and the counter is not
144 ExecutionContext
executionCtx(
145 [](const ActionActiveStack
*) { return ExecutionContext::Skip
; });
147 auto counterInc
= [&]() { counter
++; };
152 std::vector
<StringRef
> fileNames
= {StringRef("grault.garply"),
153 StringRef("waldo.fred")};
154 std::vector
<std::pair
<unsigned, unsigned>> lineColLoc
= {{42, 7}, {24, 3}};
155 Operation
*frontOp
= createOp(&context
,
156 FileLineColLoc::get(&context
, fileNames
.front(),
157 lineColLoc
.front().first
,
158 lineColLoc
.front().second
),
160 Operation
*backOp
= createOp(&context
,
161 FileLineColLoc::get(&context
, fileNames
.back(),
162 lineColLoc
.back().first
,
163 lineColLoc
.back().second
),
166 block
.push_back(frontOp
);
167 block
.push_back(backOp
);
169 FileLineColLocBreakpointManager breakpointManager
;
170 executionCtx
.addBreakpointManager(&breakpointManager
);
174 executionCtx(counterInc
, FileLineColLocTestingAction({&block
}));
175 EXPECT_EQ(counter
, 1);
177 auto *breakpoint
= breakpointManager
.addBreakpoint(
178 fileNames
.front(), lineColLoc
.front().first
, lineColLoc
.front().second
);
180 executionCtx(counterInc
, FileLineColLocTestingAction({&block
}));
181 EXPECT_EQ(counter
, 0);
182 breakpoint
->disable();
183 executionCtx(counterInc
, FileLineColLocTestingAction({&block
}));
184 EXPECT_EQ(counter
, 1);
186 breakpoint
= breakpointManager
.addBreakpoint(
187 fileNames
.back(), lineColLoc
.back().first
, lineColLoc
.back().second
);
189 executionCtx(counterInc
, FileLineColLocTestingAction({&block
}));
190 EXPECT_EQ(counter
, 0);
191 breakpoint
->disable();
192 executionCtx(counterInc
, FileLineColLocTestingAction({&block
}));
193 EXPECT_EQ(counter
, 1);
196 TEST(FileLineColLocBreakpointManager
, RegionMatch
) {
197 // This test will process a region and check various situation with
198 // a breakpoint hitting or not based on the location attached.
199 // When a breakpoint hits, the action is skipped and the counter is not
201 ExecutionContext
executionCtx(
202 [](const ActionActiveStack
*) { return ExecutionContext::Skip
; });
204 auto counterInc
= [&]() { counter
++; };
209 StringRef
fileName("plugh.xyzzy");
210 unsigned line
= 42, col
= 7;
211 Operation
*containerOp
=
212 createOp(&context
, FileLineColLoc::get(&context
, fileName
, line
, col
),
213 "containerOperation", 1);
214 Region
®ion
= containerOp
->getRegion(0);
216 FileLineColLocBreakpointManager breakpointManager
;
217 executionCtx
.addBreakpointManager(&breakpointManager
);
221 executionCtx(counterInc
, FileLineColLocTestingAction({®ion
}));
222 EXPECT_EQ(counter
, 1);
223 auto *breakpoint
= breakpointManager
.addBreakpoint(fileName
, line
, col
);
224 executionCtx(counterInc
, FileLineColLocTestingAction({®ion
}));
225 EXPECT_EQ(counter
, 1);
226 breakpoint
->disable();
227 executionCtx(counterInc
, FileLineColLocTestingAction({®ion
}));
228 EXPECT_EQ(counter
, 2);
230 containerOp
->destroy();