brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.4 KiB · 642adff Raw
353 lines · cpp
1//===- ExecutionContextTest.cpp - Debug Execution Context first impl ------===//2//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "mlir/Debug/ExecutionContext.h"10#include "mlir/Debug/BreakpointManagers/TagBreakpointManager.h"11#include "llvm/ADT/MapVector.h"12#include "gmock/gmock.h"13 14using namespace mlir;15using namespace mlir::tracing;16 17namespace {18struct DebuggerAction : public ActionImpl<DebuggerAction> {19  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(DebuggerAction)20  static constexpr StringLiteral tag = "debugger-action";21};22struct OtherAction : public ActionImpl<OtherAction> {23  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(OtherAction)24  static constexpr StringLiteral tag = "other-action";25};26struct ThirdAction : public ActionImpl<ThirdAction> {27  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(ThirdAction)28  static constexpr StringLiteral tag = "third-action";29};30 31// Simple action that does nothing.32void noOp() {}33 34/// This test executes a stack of nested action and check that the backtrace is35/// as expect.36TEST(ExecutionContext, ActionActiveStackTest) {37 38  // We'll break three time, once on each action, the backtraces should match39  // each of the entries here.40  std::vector<std::vector<StringRef>> expectedStacks = {41      {DebuggerAction::tag},42      {OtherAction::tag, DebuggerAction::tag},43      {ThirdAction::tag, OtherAction::tag, DebuggerAction::tag}};44 45  auto checkStacks = [&](const ActionActiveStack *backtrace,46                         const std::vector<StringRef> &currentStack) {47    ASSERT_EQ((int)currentStack.size(), backtrace->getDepth() + 1);48    for (StringRef stackEntry : currentStack) {49      ASSERT_NE(backtrace, nullptr);50      ASSERT_EQ(stackEntry, backtrace->getAction().getTag());51      backtrace = backtrace->getParent();52    }53  };54 55  std::vector<ExecutionContext::Control> controlSequence = {56      ExecutionContext::Step, ExecutionContext::Step, ExecutionContext::Apply};57  int idx = 0;58  StringRef current;59  int currentDepth = -1;60  auto onBreakpoint = [&](const ActionActiveStack *backtrace) {61    current = backtrace->getAction().getTag();62    currentDepth = backtrace->getDepth();63    checkStacks(backtrace, expectedStacks[idx]);64    return controlSequence[idx++];65  };66 67  TagBreakpointManager simpleManager;68  ExecutionContext executionCtx(onBreakpoint);69  executionCtx.addBreakpointManager(&simpleManager);70  std::vector<TagBreakpoint *> breakpoints;71  breakpoints.push_back(simpleManager.addBreakpoint(DebuggerAction::tag));72  breakpoints.push_back(simpleManager.addBreakpoint(OtherAction::tag));73  breakpoints.push_back(simpleManager.addBreakpoint(ThirdAction::tag));74 75  auto third = [&]() {76    EXPECT_EQ(current, ThirdAction::tag);77    EXPECT_EQ(currentDepth, 2);78  };79  auto nested = [&]() {80    EXPECT_EQ(current, OtherAction::tag);81    EXPECT_EQ(currentDepth, 1);82    executionCtx(third, ThirdAction{});83  };84  auto original = [&]() {85    EXPECT_EQ(current, DebuggerAction::tag);86    EXPECT_EQ(currentDepth, 0);87    executionCtx(nested, OtherAction{});88    return;89  };90 91  executionCtx(original, DebuggerAction{});92}93 94TEST(ExecutionContext, DebuggerTest) {95  // Check matching and non matching breakpoints, with various enable/disable96  // schemes.97  int match = 0;98  auto onBreakpoint = [&match](const ActionActiveStack *backtrace) {99    match++;100    return ExecutionContext::Skip;101  };102  TagBreakpointManager simpleManager;103  ExecutionContext executionCtx(onBreakpoint);104  executionCtx.addBreakpointManager(&simpleManager);105 106  executionCtx(noOp, DebuggerAction{});107  EXPECT_EQ(match, 0);108 109  Breakpoint *dbgBreakpoint = simpleManager.addBreakpoint(DebuggerAction::tag);110  executionCtx(noOp, DebuggerAction{});111  EXPECT_EQ(match, 1);112 113  dbgBreakpoint->disable();114  executionCtx(noOp, DebuggerAction{});115  EXPECT_EQ(match, 1);116 117  dbgBreakpoint->enable();118  executionCtx(noOp, DebuggerAction{});119  EXPECT_EQ(match, 2);120 121  executionCtx(noOp, OtherAction{});122  EXPECT_EQ(match, 2);123}124 125TEST(ExecutionContext, ApplyTest) {126  // Test the "apply" control.127  std::vector<StringRef> tagSequence = {DebuggerAction::tag};128  std::vector<ExecutionContext::Control> controlSequence = {129      ExecutionContext::Apply};130  int idx = 0, counter = 0;131  auto onBreakpoint = [&](const ActionActiveStack *backtrace) {132    ++counter;133    EXPECT_EQ(tagSequence[idx], backtrace->getAction().getTag());134    return controlSequence[idx++];135  };136  auto callback = [&]() { EXPECT_EQ(counter, 1); };137  TagBreakpointManager simpleManager;138  ExecutionContext executionCtx(onBreakpoint);139  executionCtx.addBreakpointManager(&simpleManager);140  simpleManager.addBreakpoint(DebuggerAction::tag);141 142  executionCtx(callback, DebuggerAction{});143  EXPECT_EQ(counter, 1);144}145 146TEST(ExecutionContext, SkipTest) {147  // Test the "skip" control.148  std::vector<StringRef> tagSequence = {DebuggerAction::tag,149                                        DebuggerAction::tag};150  std::vector<ExecutionContext::Control> controlSequence = {151      ExecutionContext::Apply, ExecutionContext::Skip};152  int idx = 0, counter = 0, executionCounter = 0;153  auto onBreakpoint = [&](const ActionActiveStack *backtrace) {154    ++counter;155    EXPECT_EQ(tagSequence[idx], backtrace->getAction().getTag());156    return controlSequence[idx++];157  };158  auto callback = [&]() { ++executionCounter; };159  TagBreakpointManager simpleManager;160  ExecutionContext executionCtx(onBreakpoint);161  executionCtx.addBreakpointManager(&simpleManager);162  simpleManager.addBreakpoint(DebuggerAction::tag);163 164  executionCtx(callback, DebuggerAction{});165  executionCtx(callback, DebuggerAction{});166  EXPECT_EQ(counter, 2);167  EXPECT_EQ(executionCounter, 1);168}169 170TEST(ExecutionContext, StepApplyTest) {171  // Test the "step" control with a nested action.172  std::vector<StringRef> tagSequence = {DebuggerAction::tag, OtherAction::tag};173  std::vector<ExecutionContext::Control> controlSequence = {174      ExecutionContext::Step, ExecutionContext::Apply};175  int idx = 0, counter = 0;176  auto onBreakpoint = [&](const ActionActiveStack *backtrace) {177    ++counter;178    EXPECT_EQ(tagSequence[idx], backtrace->getAction().getTag());179    return controlSequence[idx++];180  };181  TagBreakpointManager simpleManager;182  ExecutionContext executionCtx(onBreakpoint);183  executionCtx.addBreakpointManager(&simpleManager);184  simpleManager.addBreakpoint(DebuggerAction::tag);185  auto nested = [&]() { EXPECT_EQ(counter, 2); };186  auto original = [&]() {187    EXPECT_EQ(counter, 1);188    executionCtx(nested, OtherAction{});189  };190 191  executionCtx(original, DebuggerAction{});192  EXPECT_EQ(counter, 2);193}194 195TEST(ExecutionContext, StepNothingInsideTest) {196  // Test the "step" control without a nested action.197  std::vector<StringRef> tagSequence = {DebuggerAction::tag,198                                        DebuggerAction::tag};199  std::vector<ExecutionContext::Control> controlSequence = {200      ExecutionContext::Step, ExecutionContext::Step};201  int idx = 0, counter = 0;202  auto onBreakpoint = [&](const ActionActiveStack *backtrace) {203    ++counter;204    EXPECT_EQ(tagSequence[idx], backtrace->getAction().getTag());205    return controlSequence[idx++];206  };207  auto callback = [&]() { EXPECT_EQ(counter, 1); };208  TagBreakpointManager simpleManager;209  ExecutionContext executionCtx(onBreakpoint);210  executionCtx.addBreakpointManager(&simpleManager);211  simpleManager.addBreakpoint(DebuggerAction::tag);212 213  executionCtx(callback, DebuggerAction{});214  EXPECT_EQ(counter, 2);215}216 217TEST(ExecutionContext, NextTest) {218  // Test the "next" control.219  std::vector<StringRef> tagSequence = {DebuggerAction::tag,220                                        DebuggerAction::tag};221  std::vector<ExecutionContext::Control> controlSequence = {222      ExecutionContext::Next, ExecutionContext::Next};223  int idx = 0, counter = 0;224  auto onBreakpoint = [&](const ActionActiveStack *backtrace) {225    ++counter;226    EXPECT_EQ(tagSequence[idx], backtrace->getAction().getTag());227    return controlSequence[idx++];228  };229  auto callback = [&]() { EXPECT_EQ(counter, 1); };230  TagBreakpointManager simpleManager;231  ExecutionContext executionCtx(onBreakpoint);232  executionCtx.addBreakpointManager(&simpleManager);233  simpleManager.addBreakpoint(DebuggerAction::tag);234 235  executionCtx(callback, DebuggerAction{});236  EXPECT_EQ(counter, 2);237}238 239TEST(ExecutionContext, FinishTest) {240  // Test the "finish" control.241  std::vector<StringRef> tagSequence = {DebuggerAction::tag, OtherAction::tag,242                                        DebuggerAction::tag};243  std::vector<ExecutionContext::Control> controlSequence = {244      ExecutionContext::Step, ExecutionContext::Finish,245      ExecutionContext::Apply};246  int idx = 0, counter = 0;247  auto onBreakpoint = [&](const ActionActiveStack *backtrace) {248    ++counter;249    EXPECT_EQ(tagSequence[idx], backtrace->getAction().getTag());250    return controlSequence[idx++];251  };252  TagBreakpointManager simpleManager;253  ExecutionContext executionCtx(onBreakpoint);254  executionCtx.addBreakpointManager(&simpleManager);255  simpleManager.addBreakpoint(DebuggerAction::tag);256  auto nested = [&]() { EXPECT_EQ(counter, 2); };257  auto original = [&]() {258    EXPECT_EQ(counter, 1);259    executionCtx(nested, OtherAction{});260    EXPECT_EQ(counter, 2);261  };262 263  executionCtx(original, DebuggerAction{});264  EXPECT_EQ(counter, 3);265}266 267TEST(ExecutionContext, FinishBreakpointInNestedTest) {268  // Test the "finish" control with a breakpoint in the nested action.269  std::vector<StringRef> tagSequence = {OtherAction::tag, DebuggerAction::tag};270  std::vector<ExecutionContext::Control> controlSequence = {271      ExecutionContext::Finish, ExecutionContext::Apply};272  int idx = 0, counter = 0;273  auto onBreakpoint = [&](const ActionActiveStack *backtrace) {274    ++counter;275    EXPECT_EQ(tagSequence[idx], backtrace->getAction().getTag());276    return controlSequence[idx++];277  };278  TagBreakpointManager simpleManager;279  ExecutionContext executionCtx(onBreakpoint);280  executionCtx.addBreakpointManager(&simpleManager);281  simpleManager.addBreakpoint(OtherAction::tag);282 283  auto nested = [&]() { EXPECT_EQ(counter, 1); };284  auto original = [&]() {285    EXPECT_EQ(counter, 0);286    executionCtx(nested, OtherAction{});287    EXPECT_EQ(counter, 1);288  };289 290  executionCtx(original, DebuggerAction{});291  EXPECT_EQ(counter, 2);292}293 294TEST(ExecutionContext, FinishNothingBackTest) {295  // Test the "finish" control without a nested action.296  std::vector<StringRef> tagSequence = {DebuggerAction::tag};297  std::vector<ExecutionContext::Control> controlSequence = {298      ExecutionContext::Finish};299  int idx = 0, counter = 0;300  auto onBreakpoint = [&](const ActionActiveStack *backtrace) {301    ++counter;302    EXPECT_EQ(tagSequence[idx], backtrace->getAction().getTag());303    return controlSequence[idx++];304  };305  auto callback = [&]() { EXPECT_EQ(counter, 1); };306  TagBreakpointManager simpleManager;307  ExecutionContext executionCtx(onBreakpoint);308  executionCtx.addBreakpointManager(&simpleManager);309  simpleManager.addBreakpoint(DebuggerAction::tag);310 311  executionCtx(callback, DebuggerAction{});312  EXPECT_EQ(counter, 1);313}314 315TEST(ExecutionContext, EnableDisableBreakpointOnCallback) {316  // Test enabling and disabling breakpoints while executing the action.317  std::vector<StringRef> tagSequence = {DebuggerAction::tag, ThirdAction::tag,318                                        OtherAction::tag, DebuggerAction::tag};319  std::vector<ExecutionContext::Control> controlSequence = {320      ExecutionContext::Apply, ExecutionContext::Finish,321      ExecutionContext::Finish, ExecutionContext::Apply};322  int idx = 0, counter = 0;323  auto onBreakpoint = [&](const ActionActiveStack *backtrace) {324    ++counter;325    EXPECT_EQ(tagSequence[idx], backtrace->getAction().getTag());326    return controlSequence[idx++];327  };328 329  TagBreakpointManager simpleManager;330  ExecutionContext executionCtx(onBreakpoint);331  executionCtx.addBreakpointManager(&simpleManager);332  simpleManager.addBreakpoint(DebuggerAction::tag);333  Breakpoint *toBeDisabled = simpleManager.addBreakpoint(OtherAction::tag);334 335  auto third = [&]() { EXPECT_EQ(counter, 2); };336  auto nested = [&]() {337    EXPECT_EQ(counter, 1);338    executionCtx(third, ThirdAction{});339    EXPECT_EQ(counter, 2);340  };341  auto original = [&]() {342    EXPECT_EQ(counter, 1);343    toBeDisabled->disable();344    simpleManager.addBreakpoint(ThirdAction::tag);345    executionCtx(nested, OtherAction{});346    EXPECT_EQ(counter, 3);347  };348 349  executionCtx(original, DebuggerAction{});350  EXPECT_EQ(counter, 4);351}352} // namespace353