233 lines
8.8 KiB
C++
233 lines
8.8 KiB
C++
|
//===- 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),
|
||
|
std::nullopt, std::nullopt, std::nullopt,
|
||
|
OpaqueProperties(nullptr), std::nullopt, 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 = [&](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
|