17f069f5eSMehdi Amini //===- FileLineColLocBreakpointManagerTest.cpp - --------------------------===//
27f069f5eSMehdi Amini //
37f069f5eSMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47f069f5eSMehdi Amini // See https://llvm.org/LICENSE.txt for license information.
57f069f5eSMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67f069f5eSMehdi Amini //
77f069f5eSMehdi Amini //===----------------------------------------------------------------------===//
87f069f5eSMehdi Amini
97f069f5eSMehdi Amini #include "mlir/Debug/BreakpointManagers/FileLineColLocBreakpointManager.h"
107f069f5eSMehdi Amini #include "mlir/Debug/ExecutionContext.h"
117f069f5eSMehdi Amini #include "mlir/IR/Builders.h"
127f069f5eSMehdi Amini #include "mlir/IR/BuiltinAttributes.h"
137f069f5eSMehdi Amini #include "mlir/IR/BuiltinTypes.h"
147f069f5eSMehdi Amini #include "mlir/IR/Location.h"
157f069f5eSMehdi Amini #include "mlir/IR/OperationSupport.h"
167f069f5eSMehdi Amini #include "llvm/ADT/STLExtras.h"
177f069f5eSMehdi Amini #include "gtest/gtest.h"
187f069f5eSMehdi Amini
197f069f5eSMehdi Amini using namespace mlir;
207f069f5eSMehdi Amini using namespace mlir::tracing;
217f069f5eSMehdi Amini
createOp(MLIRContext * context,Location loc,StringRef operationName,unsigned int numRegions=0)227f069f5eSMehdi Amini static Operation *createOp(MLIRContext *context, Location loc,
237f069f5eSMehdi Amini StringRef operationName,
247f069f5eSMehdi Amini unsigned int numRegions = 0) {
257f069f5eSMehdi Amini context->allowUnregisteredDialects();
267f069f5eSMehdi Amini return Operation::create(loc, OperationName(operationName, context),
277f069f5eSMehdi Amini std::nullopt, std::nullopt, std::nullopt,
285e118f93SMehdi Amini OpaqueProperties(nullptr), std::nullopt, numRegions);
297f069f5eSMehdi Amini }
307f069f5eSMehdi Amini
317f069f5eSMehdi Amini namespace {
327f069f5eSMehdi Amini struct FileLineColLocTestingAction
337f069f5eSMehdi Amini : public ActionImpl<FileLineColLocTestingAction> {
347f069f5eSMehdi Amini MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(FileLineColLocTestingAction)
357f069f5eSMehdi Amini static constexpr StringLiteral tag = "file-line-col-loc-testing-action";
FileLineColLocTestingAction__anon99b9193c0111::FileLineColLocTestingAction367f069f5eSMehdi Amini FileLineColLocTestingAction(ArrayRef<IRUnit> irUnits)
377f069f5eSMehdi Amini : ActionImpl<FileLineColLocTestingAction>(irUnits) {}
387f069f5eSMehdi Amini };
397f069f5eSMehdi Amini
TEST(FileLineColLocBreakpointManager,OperationMatch)407f069f5eSMehdi Amini TEST(FileLineColLocBreakpointManager, OperationMatch) {
417f069f5eSMehdi Amini // This test will process a sequence of operation and check various situation
427f069f5eSMehdi Amini // with a breakpoint hitting or not based on the location attached to the
437f069f5eSMehdi Amini // operation. When a breakpoint hits, the action is skipped and the counter is
447f069f5eSMehdi Amini // not incremented.
457f069f5eSMehdi Amini ExecutionContext executionCtx(
467f069f5eSMehdi Amini [](const ActionActiveStack *) { return ExecutionContext::Skip; });
477f069f5eSMehdi Amini int counter = 0;
487f069f5eSMehdi Amini auto counterInc = [&]() { counter++; };
497f069f5eSMehdi Amini
507f069f5eSMehdi Amini // Setup
517f069f5eSMehdi Amini
527f069f5eSMehdi Amini MLIRContext context;
537f069f5eSMehdi Amini // Miscellaneous information to define operations
547f069f5eSMehdi Amini std::vector<StringRef> fileNames = {
557f069f5eSMehdi Amini StringRef("foo.bar"), StringRef("baz.qux"), StringRef("quux.corge")};
567f069f5eSMehdi Amini std::vector<std::pair<unsigned, unsigned>> lineColLoc = {{42, 7}, {24, 3}};
577f069f5eSMehdi Amini Location callee = UnknownLoc::get(&context),
587f069f5eSMehdi Amini caller = UnknownLoc::get(&context), loc = UnknownLoc::get(&context);
597f069f5eSMehdi Amini
607f069f5eSMehdi Amini // Set of operations over where we are going to be testing the functionality
617f069f5eSMehdi Amini std::vector<Operation *> operations = {
627f069f5eSMehdi Amini createOp(&context, CallSiteLoc::get(callee, caller),
637f069f5eSMehdi Amini "callSiteLocOperation"),
647f069f5eSMehdi Amini createOp(&context,
657f069f5eSMehdi Amini FileLineColLoc::get(&context, fileNames[0], lineColLoc[0].first,
667f069f5eSMehdi Amini lineColLoc[0].second),
677f069f5eSMehdi Amini "fileLineColLocOperation"),
687f069f5eSMehdi Amini createOp(&context, FusedLoc::get(&context, {}, Attribute()),
697f069f5eSMehdi Amini "fusedLocOperation"),
707f069f5eSMehdi Amini createOp(&context, NameLoc::get(StringAttr::get(&context, fileNames[2])),
717f069f5eSMehdi Amini "nameLocOperation"),
727f069f5eSMehdi Amini createOp(&context, OpaqueLoc::get<void *>(nullptr, loc),
737f069f5eSMehdi Amini "opaqueLocOperation"),
747f069f5eSMehdi Amini createOp(&context,
757f069f5eSMehdi Amini FileLineColLoc::get(&context, fileNames[1], lineColLoc[1].first,
767f069f5eSMehdi Amini lineColLoc[1].second),
777f069f5eSMehdi Amini "anotherFileLineColLocOperation"),
787f069f5eSMehdi Amini createOp(&context, UnknownLoc::get(&context), "unknownLocOperation"),
797f069f5eSMehdi Amini };
807f069f5eSMehdi Amini
817f069f5eSMehdi Amini FileLineColLocBreakpointManager breakpointManager;
827f069f5eSMehdi Amini executionCtx.addBreakpointManager(&breakpointManager);
837f069f5eSMehdi Amini
847f069f5eSMehdi Amini // Test
857f069f5eSMehdi Amini
867f069f5eSMehdi Amini // Basic case is that no breakpoint is set and the counter is incremented for
877f069f5eSMehdi Amini // every op.
887f069f5eSMehdi Amini auto checkNoMatch = [&]() {
897f069f5eSMehdi Amini counter = 0;
907f069f5eSMehdi Amini for (auto enumeratedOp : llvm::enumerate(operations)) {
917f069f5eSMehdi Amini executionCtx(counterInc,
927f069f5eSMehdi Amini FileLineColLocTestingAction({enumeratedOp.value()}));
937f069f5eSMehdi Amini EXPECT_EQ(counter, static_cast<int>(enumeratedOp.index() + 1));
947f069f5eSMehdi Amini }
957f069f5eSMehdi Amini };
967f069f5eSMehdi Amini checkNoMatch();
977f069f5eSMehdi Amini
987f069f5eSMehdi Amini // Set a breakpoint matching only the second operation in the list.
997f069f5eSMehdi Amini auto *breakpoint = breakpointManager.addBreakpoint(
1007f069f5eSMehdi Amini fileNames[0], lineColLoc[0].first, lineColLoc[0].second);
101*1893a374SMehdi Amini auto checkMatchIdxs = [&](const DenseSet<int> &idxs) {
1027f069f5eSMehdi Amini counter = 0;
1037f069f5eSMehdi Amini int reference = 0;
1047f069f5eSMehdi Amini for (int i = 0; i < (int)operations.size(); ++i) {
1057f069f5eSMehdi Amini executionCtx(counterInc, FileLineColLocTestingAction({operations[i]}));
1067f069f5eSMehdi Amini if (!idxs.contains(i))
1077f069f5eSMehdi Amini reference++;
1087f069f5eSMehdi Amini EXPECT_EQ(counter, reference);
1097f069f5eSMehdi Amini }
1107f069f5eSMehdi Amini };
1117f069f5eSMehdi Amini checkMatchIdxs({1});
1127f069f5eSMehdi Amini
1137f069f5eSMehdi Amini // Check that disabling the breakpoing brings us back to the original
1147f069f5eSMehdi Amini // behavior.
1157f069f5eSMehdi Amini breakpoint->disable();
1167f069f5eSMehdi Amini checkNoMatch();
1177f069f5eSMehdi Amini
1187f069f5eSMehdi Amini // Adding a breakpoint that won't match any location shouldn't affect the
1197f069f5eSMehdi Amini // behavior.
1207f069f5eSMehdi Amini breakpointManager.addBreakpoint(StringRef("random.file"), 3, 14);
1217f069f5eSMehdi Amini checkNoMatch();
1227f069f5eSMehdi Amini
1237f069f5eSMehdi Amini // Set a breakpoint matching only the fifth operation in the list.
1247f069f5eSMehdi Amini breakpointManager.addBreakpoint(fileNames[1], lineColLoc[1].first,
1257f069f5eSMehdi Amini lineColLoc[1].second);
1267f069f5eSMehdi Amini counter = 0;
1277f069f5eSMehdi Amini checkMatchIdxs({5});
1287f069f5eSMehdi Amini
1297f069f5eSMehdi Amini // Re-enable the breakpoint matching only the second operation in the list.
1307f069f5eSMehdi Amini // We now expect matching of operations 1 and 5.
1317f069f5eSMehdi Amini breakpoint->enable();
1327f069f5eSMehdi Amini checkMatchIdxs({1, 5});
1337f069f5eSMehdi Amini
1347f069f5eSMehdi Amini for (auto *op : operations) {
1357f069f5eSMehdi Amini op->destroy();
1367f069f5eSMehdi Amini }
1377f069f5eSMehdi Amini }
1387f069f5eSMehdi Amini
TEST(FileLineColLocBreakpointManager,BlockMatch)1397f069f5eSMehdi Amini TEST(FileLineColLocBreakpointManager, BlockMatch) {
1407f069f5eSMehdi Amini // This test will process a block and check various situation with
1417f069f5eSMehdi Amini // a breakpoint hitting or not based on the location attached.
1427f069f5eSMehdi Amini // When a breakpoint hits, the action is skipped and the counter is not
1437f069f5eSMehdi Amini // incremented.
1447f069f5eSMehdi Amini ExecutionContext executionCtx(
1457f069f5eSMehdi Amini [](const ActionActiveStack *) { return ExecutionContext::Skip; });
1467f069f5eSMehdi Amini int counter = 0;
1477f069f5eSMehdi Amini auto counterInc = [&]() { counter++; };
1487f069f5eSMehdi Amini
1497f069f5eSMehdi Amini // Setup
1507f069f5eSMehdi Amini
1517f069f5eSMehdi Amini MLIRContext context;
1527f069f5eSMehdi Amini std::vector<StringRef> fileNames = {StringRef("grault.garply"),
1537f069f5eSMehdi Amini StringRef("waldo.fred")};
1547f069f5eSMehdi Amini std::vector<std::pair<unsigned, unsigned>> lineColLoc = {{42, 7}, {24, 3}};
1557f069f5eSMehdi Amini Operation *frontOp = createOp(&context,
1567f069f5eSMehdi Amini FileLineColLoc::get(&context, fileNames.front(),
1577f069f5eSMehdi Amini lineColLoc.front().first,
1587f069f5eSMehdi Amini lineColLoc.front().second),
1597f069f5eSMehdi Amini "firstOperation");
1607f069f5eSMehdi Amini Operation *backOp = createOp(&context,
1617f069f5eSMehdi Amini FileLineColLoc::get(&context, fileNames.back(),
1627f069f5eSMehdi Amini lineColLoc.back().first,
1637f069f5eSMehdi Amini lineColLoc.back().second),
1647f069f5eSMehdi Amini "secondOperation");
1657f069f5eSMehdi Amini Block block;
1667f069f5eSMehdi Amini block.push_back(frontOp);
1677f069f5eSMehdi Amini block.push_back(backOp);
1687f069f5eSMehdi Amini
1697f069f5eSMehdi Amini FileLineColLocBreakpointManager breakpointManager;
1707f069f5eSMehdi Amini executionCtx.addBreakpointManager(&breakpointManager);
1717f069f5eSMehdi Amini
1727f069f5eSMehdi Amini // Test
1737f069f5eSMehdi Amini
1747f069f5eSMehdi Amini executionCtx(counterInc, FileLineColLocTestingAction({&block}));
1757f069f5eSMehdi Amini EXPECT_EQ(counter, 1);
1767f069f5eSMehdi Amini
1777f069f5eSMehdi Amini auto *breakpoint = breakpointManager.addBreakpoint(
1787f069f5eSMehdi Amini fileNames.front(), lineColLoc.front().first, lineColLoc.front().second);
1797f069f5eSMehdi Amini counter = 0;
1807f069f5eSMehdi Amini executionCtx(counterInc, FileLineColLocTestingAction({&block}));
1817f069f5eSMehdi Amini EXPECT_EQ(counter, 0);
1827f069f5eSMehdi Amini breakpoint->disable();
1837f069f5eSMehdi Amini executionCtx(counterInc, FileLineColLocTestingAction({&block}));
1847f069f5eSMehdi Amini EXPECT_EQ(counter, 1);
1857f069f5eSMehdi Amini
1867f069f5eSMehdi Amini breakpoint = breakpointManager.addBreakpoint(
1877f069f5eSMehdi Amini fileNames.back(), lineColLoc.back().first, lineColLoc.back().second);
1887f069f5eSMehdi Amini counter = 0;
1897f069f5eSMehdi Amini executionCtx(counterInc, FileLineColLocTestingAction({&block}));
1907f069f5eSMehdi Amini EXPECT_EQ(counter, 0);
1917f069f5eSMehdi Amini breakpoint->disable();
1927f069f5eSMehdi Amini executionCtx(counterInc, FileLineColLocTestingAction({&block}));
1937f069f5eSMehdi Amini EXPECT_EQ(counter, 1);
1947f069f5eSMehdi Amini }
1957f069f5eSMehdi Amini
TEST(FileLineColLocBreakpointManager,RegionMatch)1967f069f5eSMehdi Amini TEST(FileLineColLocBreakpointManager, RegionMatch) {
1977f069f5eSMehdi Amini // This test will process a region and check various situation with
1987f069f5eSMehdi Amini // a breakpoint hitting or not based on the location attached.
1997f069f5eSMehdi Amini // When a breakpoint hits, the action is skipped and the counter is not
2007f069f5eSMehdi Amini // incremented.
2017f069f5eSMehdi Amini ExecutionContext executionCtx(
2027f069f5eSMehdi Amini [](const ActionActiveStack *) { return ExecutionContext::Skip; });
2037f069f5eSMehdi Amini int counter = 0;
2047f069f5eSMehdi Amini auto counterInc = [&]() { counter++; };
2057f069f5eSMehdi Amini
2067f069f5eSMehdi Amini // Setup
2077f069f5eSMehdi Amini
2087f069f5eSMehdi Amini MLIRContext context;
2097f069f5eSMehdi Amini StringRef fileName("plugh.xyzzy");
2107f069f5eSMehdi Amini unsigned line = 42, col = 7;
2117f069f5eSMehdi Amini Operation *containerOp =
2127f069f5eSMehdi Amini createOp(&context, FileLineColLoc::get(&context, fileName, line, col),
2137f069f5eSMehdi Amini "containerOperation", 1);
2147f069f5eSMehdi Amini Region ®ion = containerOp->getRegion(0);
2157f069f5eSMehdi Amini
2167f069f5eSMehdi Amini FileLineColLocBreakpointManager breakpointManager;
2177f069f5eSMehdi Amini executionCtx.addBreakpointManager(&breakpointManager);
2187f069f5eSMehdi Amini
2197f069f5eSMehdi Amini // Test
2207f069f5eSMehdi Amini counter = 0;
2217f069f5eSMehdi Amini executionCtx(counterInc, FileLineColLocTestingAction({®ion}));
2227f069f5eSMehdi Amini EXPECT_EQ(counter, 1);
2237f069f5eSMehdi Amini auto *breakpoint = breakpointManager.addBreakpoint(fileName, line, col);
2247f069f5eSMehdi Amini executionCtx(counterInc, FileLineColLocTestingAction({®ion}));
2257f069f5eSMehdi Amini EXPECT_EQ(counter, 1);
2267f069f5eSMehdi Amini breakpoint->disable();
2277f069f5eSMehdi Amini executionCtx(counterInc, FileLineColLocTestingAction({®ion}));
2287f069f5eSMehdi Amini EXPECT_EQ(counter, 2);
2297f069f5eSMehdi Amini
2307f069f5eSMehdi Amini containerOp->destroy();
2317f069f5eSMehdi Amini }
2327f069f5eSMehdi Amini } // namespace
233