| //===- FileLineColLocBreakpointManagerTest.cpp - --------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "mlir/Debug/BreakpointManagers/FileLineColLocBreakpointManager.h" |
| #include "mlir/Debug/ExecutionContext.h" |
| #include "mlir/IR/Builders.h" |
| #include "mlir/IR/BuiltinAttributes.h" |
| #include "mlir/IR/BuiltinTypes.h" |
| #include "mlir/IR/Location.h" |
| #include "mlir/IR/OperationSupport.h" |
| #include "llvm/ADT/STLExtras.h" |
| #include "gtest/gtest.h" |
| |
| using namespace mlir; |
| using namespace mlir::tracing; |
| |
| static Operation *createOp(MLIRContext *context, Location loc, |
| StringRef operationName, |
| unsigned int numRegions = 0) { |
| context->allowUnregisteredDialects(); |
| return Operation::create(loc, OperationName(operationName, context), {}, {}, |
| NamedAttrList(), OpaqueProperties(nullptr), {}, |
| numRegions); |
| } |
| |
| namespace { |
| struct FileLineColLocTestingAction |
| : public ActionImpl<FileLineColLocTestingAction> { |
| MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(FileLineColLocTestingAction) |
| static constexpr StringLiteral tag = "file-line-col-loc-testing-action"; |
| FileLineColLocTestingAction(ArrayRef<IRUnit> irUnits) |
| : ActionImpl<FileLineColLocTestingAction>(irUnits) {} |
| }; |
| |
| TEST(FileLineColLocBreakpointManager, OperationMatch) { |
| // This test will process a sequence of operation and check various situation |
| // with a breakpoint hitting or not based on the location attached to the |
| // operation. When a breakpoint hits, the action is skipped and the counter is |
| // not incremented. |
| ExecutionContext executionCtx( |
| [](const ActionActiveStack *) { return ExecutionContext::Skip; }); |
| int counter = 0; |
| auto counterInc = [&]() { counter++; }; |
| |
| // Setup |
| |
| MLIRContext context; |
| // Miscellaneous information to define operations |
| std::vector<StringRef> fileNames = { |
| StringRef("foo.bar"), StringRef("baz.qux"), StringRef("quux.corge")}; |
| std::vector<std::pair<unsigned, unsigned>> lineColLoc = {{42, 7}, {24, 3}}; |
| Location callee = UnknownLoc::get(&context), |
| caller = UnknownLoc::get(&context), loc = UnknownLoc::get(&context); |
| |
| // Set of operations over where we are going to be testing the functionality |
| std::vector<Operation *> operations = { |
| createOp(&context, CallSiteLoc::get(callee, caller), |
| "callSiteLocOperation"), |
| createOp(&context, |
| FileLineColLoc::get(&context, fileNames[0], lineColLoc[0].first, |
| lineColLoc[0].second), |
| "fileLineColLocOperation"), |
| createOp(&context, FusedLoc::get(&context, {}, Attribute()), |
| "fusedLocOperation"), |
| createOp(&context, NameLoc::get(StringAttr::get(&context, fileNames[2])), |
| "nameLocOperation"), |
| createOp(&context, OpaqueLoc::get<void *>(nullptr, loc), |
| "opaqueLocOperation"), |
| createOp(&context, |
| FileLineColLoc::get(&context, fileNames[1], lineColLoc[1].first, |
| lineColLoc[1].second), |
| "anotherFileLineColLocOperation"), |
| createOp(&context, UnknownLoc::get(&context), "unknownLocOperation"), |
| }; |
| |
| FileLineColLocBreakpointManager breakpointManager; |
| executionCtx.addBreakpointManager(&breakpointManager); |
| |
| // Test |
| |
| // Basic case is that no breakpoint is set and the counter is incremented for |
| // every op. |
| auto checkNoMatch = [&]() { |
| counter = 0; |
| for (auto enumeratedOp : llvm::enumerate(operations)) { |
| executionCtx(counterInc, |
| FileLineColLocTestingAction({enumeratedOp.value()})); |
| EXPECT_EQ(counter, static_cast<int>(enumeratedOp.index() + 1)); |
| } |
| }; |
| checkNoMatch(); |
| |
| // Set a breakpoint matching only the second operation in the list. |
| auto *breakpoint = breakpointManager.addBreakpoint( |
| fileNames[0], lineColLoc[0].first, lineColLoc[0].second); |
| auto checkMatchIdxs = [&](const DenseSet<int> &idxs) { |
| counter = 0; |
| int reference = 0; |
| for (int i = 0; i < (int)operations.size(); ++i) { |
| executionCtx(counterInc, FileLineColLocTestingAction({operations[i]})); |
| if (!idxs.contains(i)) |
| reference++; |
| EXPECT_EQ(counter, reference); |
| } |
| }; |
| checkMatchIdxs({1}); |
| |
| // Check that disabling the breakpoing brings us back to the original |
| // behavior. |
| breakpoint->disable(); |
| checkNoMatch(); |
| |
| // Adding a breakpoint that won't match any location shouldn't affect the |
| // behavior. |
| breakpointManager.addBreakpoint(StringRef("random.file"), 3, 14); |
| checkNoMatch(); |
| |
| // Set a breakpoint matching only the fifth operation in the list. |
| breakpointManager.addBreakpoint(fileNames[1], lineColLoc[1].first, |
| lineColLoc[1].second); |
| counter = 0; |
| checkMatchIdxs({5}); |
| |
| // Re-enable the breakpoint matching only the second operation in the list. |
| // We now expect matching of operations 1 and 5. |
| breakpoint->enable(); |
| checkMatchIdxs({1, 5}); |
| |
| for (auto *op : operations) { |
| op->destroy(); |
| } |
| } |
| |
| TEST(FileLineColLocBreakpointManager, BlockMatch) { |
| // This test will process a block and check various situation with |
| // a breakpoint hitting or not based on the location attached. |
| // When a breakpoint hits, the action is skipped and the counter is not |
| // incremented. |
| ExecutionContext executionCtx( |
| [](const ActionActiveStack *) { return ExecutionContext::Skip; }); |
| int counter = 0; |
| auto counterInc = [&]() { counter++; }; |
| |
| // Setup |
| |
| MLIRContext context; |
| std::vector<StringRef> fileNames = {StringRef("grault.garply"), |
| StringRef("waldo.fred")}; |
| std::vector<std::pair<unsigned, unsigned>> lineColLoc = {{42, 7}, {24, 3}}; |
| Operation *frontOp = createOp(&context, |
| FileLineColLoc::get(&context, fileNames.front(), |
| lineColLoc.front().first, |
| lineColLoc.front().second), |
| "firstOperation"); |
| Operation *backOp = createOp(&context, |
| FileLineColLoc::get(&context, fileNames.back(), |
| lineColLoc.back().first, |
| lineColLoc.back().second), |
| "secondOperation"); |
| Block block; |
| block.push_back(frontOp); |
| block.push_back(backOp); |
| |
| FileLineColLocBreakpointManager breakpointManager; |
| executionCtx.addBreakpointManager(&breakpointManager); |
| |
| // Test |
| |
| executionCtx(counterInc, FileLineColLocTestingAction({&block})); |
| EXPECT_EQ(counter, 1); |
| |
| auto *breakpoint = breakpointManager.addBreakpoint( |
| fileNames.front(), lineColLoc.front().first, lineColLoc.front().second); |
| counter = 0; |
| executionCtx(counterInc, FileLineColLocTestingAction({&block})); |
| EXPECT_EQ(counter, 0); |
| breakpoint->disable(); |
| executionCtx(counterInc, FileLineColLocTestingAction({&block})); |
| EXPECT_EQ(counter, 1); |
| |
| breakpoint = breakpointManager.addBreakpoint( |
| fileNames.back(), lineColLoc.back().first, lineColLoc.back().second); |
| counter = 0; |
| executionCtx(counterInc, FileLineColLocTestingAction({&block})); |
| EXPECT_EQ(counter, 0); |
| breakpoint->disable(); |
| executionCtx(counterInc, FileLineColLocTestingAction({&block})); |
| EXPECT_EQ(counter, 1); |
| } |
| |
| TEST(FileLineColLocBreakpointManager, RegionMatch) { |
| // This test will process a region and check various situation with |
| // a breakpoint hitting or not based on the location attached. |
| // When a breakpoint hits, the action is skipped and the counter is not |
| // incremented. |
| ExecutionContext executionCtx( |
| [](const ActionActiveStack *) { return ExecutionContext::Skip; }); |
| int counter = 0; |
| auto counterInc = [&]() { counter++; }; |
| |
| // Setup |
| |
| MLIRContext context; |
| StringRef fileName("plugh.xyzzy"); |
| unsigned line = 42, col = 7; |
| Operation *containerOp = |
| createOp(&context, FileLineColLoc::get(&context, fileName, line, col), |
| "containerOperation", 1); |
| Region ®ion = containerOp->getRegion(0); |
| |
| FileLineColLocBreakpointManager breakpointManager; |
| executionCtx.addBreakpointManager(&breakpointManager); |
| |
| // Test |
| counter = 0; |
| executionCtx(counterInc, FileLineColLocTestingAction({®ion})); |
| EXPECT_EQ(counter, 1); |
| auto *breakpoint = breakpointManager.addBreakpoint(fileName, line, col); |
| executionCtx(counterInc, FileLineColLocTestingAction({®ion})); |
| EXPECT_EQ(counter, 1); |
| breakpoint->disable(); |
| executionCtx(counterInc, FileLineColLocTestingAction({®ion})); |
| EXPECT_EQ(counter, 2); |
| |
| containerOp->destroy(); |
| } |
| } // namespace |