// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.debug;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ArtCommandBuilder;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.naming.ClassNamingForNameMapper;
import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRange;
import com.android.tools.r8.naming.MemberNaming;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.MemberNaming.Signature;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.TestDescriptionWatcher;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import it.unimi.dsi.fastutil.longs.LongArrayList;
import it.unimi.dsi.fastutil.longs.LongList;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import it.unimi.dsi.fastutil.longs.LongSet;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.TreeMap;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.harmony.jpda.tests.framework.TestErrorException;
import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket;
import org.apache.harmony.jpda.tests.framework.jdwp.Event;
import org.apache.harmony.jpda.tests.framework.jdwp.EventBuilder;
import org.apache.harmony.jpda.tests.framework.jdwp.EventPacket;
import org.apache.harmony.jpda.tests.framework.jdwp.Frame.Variable;
import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands;
import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands.ObjectReferenceCommandSet;
import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands.ReferenceTypeCommandSet;
import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands.StackFrameCommandSet;
import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants.Error;
import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants.EventKind;
import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants.StepDepth;
import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants.StepSize;
import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants.SuspendPolicy;
import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants.TypeTag;
import org.apache.harmony.jpda.tests.framework.jdwp.Location;
import org.apache.harmony.jpda.tests.framework.jdwp.Method;
import org.apache.harmony.jpda.tests.framework.jdwp.ParsedEvent;
import org.apache.harmony.jpda.tests.framework.jdwp.ParsedEvent.EventThread;
import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
import org.apache.harmony.jpda.tests.framework.jdwp.Value;
import org.apache.harmony.jpda.tests.framework.jdwp.VmMirror;
import org.apache.harmony.jpda.tests.jdwp.share.JDWPTestCase;
import org.apache.harmony.jpda.tests.share.JPDATestOptions;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.ClassRule;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.rules.TemporaryFolder;
import org.junit.rules.TestName;

/**
 * Base class for debugging tests.
 *
 * The protocol messages are described here:
 * https://docs.oracle.com/javase/8/docs/platform/jpda/jdwp/jdwp-protocol.html
 */
public abstract class DebugTestBase extends TestBase {

  // Set to true to enable verbose logs
  private static final boolean DEBUG_TESTS = false;

  // Build-time compiled debug-test resources for Java SDK < 8. See build.gradle
  public static final Path DEBUGGEE_JAR =
      Paths.get(ToolHelper.BUILD_DIR, "test", "debug_test_resources.jar");

  // Build-time compiled debug-test resources for Java SDK 8. See build.gradle
  public static final Path DEBUGGEE_JAVA8_JAR =
      Paths.get(ToolHelper.BUILD_DIR, "test", "debug_test_resources_java8.jar");

  public static final StepFilter NO_FILTER = new StepFilter.NoStepFilter();
  public static final StepFilter INTELLIJ_FILTER = new StepFilter.IntelliJStepFilter();
  public static final StepFilter ANDROID_FILTER = new StepFilter.AndroidRuntimeStepFilter();
  private static final StepFilter DEFAULT_FILTER = NO_FILTER;

  private static final int FIRST_LINE = -1;

  static class SignatureAndLine {
    final String signature;
    int line;

    SignatureAndLine(String signature, int line) {
      this.signature = signature;
      this.line = line;
    }
  }

  public static class DebugTestParameters {

    final HashMap<String, DelayedDebugTestConfig> map = new HashMap<>();

    public DebugTestParameters add(String name, DebugTestConfig config) {
      return add(name, temp -> config);
    }

    public DebugTestParameters add(String name, DelayedDebugTestConfig config) {
      assert !map.containsKey(name);
      map.put(name, config);
      return this;
    }

    // Returns a list of parameters used in most debug tests of the form: name * config.
    public List<Object[]> build() {
      return map.entrySet().stream()
          .map(e -> new Object[] {e.getKey(), e.getValue()})
          .collect(Collectors.toList());
    }
  }

  public static DebugTestParameters parameters() {
    return new DebugTestParameters();
  }

  @ClassRule
  public static TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();

  @Rule
  public TestName testName = new TestName();

  @Rule
  public TestDescriptionWatcher watcher = new TestDescriptionWatcher();

  protected static final boolean supportsDefaultMethod(DebugTestConfig config) {
    return config.isCfRuntime()
        || ToolHelper.getMinApiLevelForDexVm().getLevel() >= AndroidApiLevel.N.getLevel();
  }

  protected final void runDebugTest(
      DebugTestConfig config, Class<?> debuggeeClass, JUnit3Wrapper.Command... commands)
      throws Throwable {
    runInternal(config, debuggeeClass.getTypeName(), Arrays.asList(commands));
  }

  protected final void runDebugTest(
      DebugTestConfig config, String debuggeeClass, JUnit3Wrapper.Command... commands)
      throws Throwable {
    runInternal(config, debuggeeClass, Arrays.asList(commands));
  }

  protected final void runDebugTest(
      DebugTestConfig config, String debuggeeClass, List<JUnit3Wrapper.Command> commands)
      throws Throwable {
    runInternal(config, debuggeeClass, commands);
  }

  private void runInternal(
      DebugTestConfig config, String debuggeeClass, List<JUnit3Wrapper.Command> commands)
      throws Throwable {
    getDebugTestRunner(config, debuggeeClass, commands).runBare();
  }

  protected DebugTestRunner getDebugTestRunner(
      DebugTestConfig config, String debuggeeClass, JUnit3Wrapper.Command... commands)
      throws Throwable {
    return getDebugTestRunner(config, debuggeeClass, Arrays.asList(commands));
  }

  protected DebugTestRunner getDebugTestRunner(
      DebugTestConfig config, String debuggeeClass, List<JUnit3Wrapper.Command> commands)
      throws Throwable {
    // Skip test due to unsupported runtime.
    Assume.assumeTrue("Skipping test " + testName.getMethodName() + " because ART is not supported",
        ToolHelper.artSupported());
    Assume.assumeTrue("Skipping test " + testName.getMethodName()
            + " because debug tests are not yet supported on Windows",
        !ToolHelper.isWindows());
    Assume.assumeTrue("Skipping test " + testName.getMethodName()
            + " because debug tests are not yet supported on device",
        ToolHelper.getDexVm().getKind() == ToolHelper.DexVm.Kind.HOST);

    ClassNameMapper classNameMapper =
        config.getProguardMap() == null
            ? null
            : ClassNameMapper.mapperFromFile(
                config.getProguardMap(), config.getMissingProguardMapAction());

    return new JUnit3Wrapper(config, debuggeeClass, commands, classNameMapper);
  }

  /**
   * Lazily debug-step an execution starting from main(String[]) in {@code debuggeeClass}.
   *
   * @return A stream of successive debuggee states.
   */
  public Stream<JUnit3Wrapper.DebuggeeState> streamDebugTest(
      DebugTestConfig config, String debuggeeClass, StepFilter filter) throws Exception {
    return streamDebugTest(
        config,
        debuggeeClass,
        breakpoint(debuggeeClass, "main", "([Ljava/lang/String;)V"),
        filter);
  }

  /**
   * Lazily debug-step an execution starting from {@code breakpoint}.
   *
   * @return A stream of successive debuggee states.
   */
  public Stream<JUnit3Wrapper.DebuggeeState> streamDebugTest(
      DebugTestConfig config,
      String debuggeeClass,
      JUnit3Wrapper.Command breakpoint,
      StepFilter filter)
      throws Exception {
    assert breakpoint instanceof JUnit3Wrapper.Command.BreakpointCommand;

    // Continuous single-step command.
    // The execution of the command pushes itself onto the command queue ensuring the next step.
    JUnit3Wrapper.Command streamCommand =
        new JUnit3Wrapper.Command() {
          @Override
          public void perform(JUnit3Wrapper testBase) {
            if (DEBUG_TESTS) {
              System.out.println("Running stream stepping command");
            }
            stepInto(filter).perform(testBase);
            assert testBase.commandsQueue.isEmpty();
            testBase.commandsQueue.push(this);
          }
        };

    // Initial setup of the debug tests. Assumes execution starts at the "main" method of the class.
    final JUnit3Wrapper wrapper =
        new JUnit3Wrapper(
            config,
            debuggeeClass,
            ImmutableList.of(breakpoint, run()),
            null);

    // Setup the initial state for the JDWP test base and run the program to the initial breakpoint.
    wrapper.prepareForStreaming();
    boolean running = true;
    while (running
        && !(wrapper.commandsQueue.isEmpty()
            && wrapper.state == JUnit3Wrapper.State.ProcessCommand)) {
      if (DEBUG_TESTS) {
        System.out.println("Running stream initialization step");
      }
      running = wrapper.mainLoopStep();
    }

    if (DEBUG_TESTS) {
      System.out.println("Finished initialization of stream");
    }
    // Add the "infinite streaming" command.
    wrapper.commandsQueue.addLast(streamCommand);
    final boolean initiallyRunning = running;

    // Construct an infinite stream of states. Each element denotes the next debuggee state reached
    // by single-stepping the program. On and after exit, all elements are null.
    return Stream.generate(
        new Supplier<JUnit3Wrapper.DebuggeeState>() {

          private boolean initial = true;
          private boolean running = initiallyRunning;

          @Override
          public JUnit3Wrapper.DebuggeeState get() {
            if (wrapper.state == JUnit3Wrapper.State.Exit) {
              return null;
            }
            assert verifyStateLocation(wrapper.getDebuggeeState());
            if (initial) {
              if (DEBUG_TESTS) {
                System.out.println("Request for initial stream state");
              }
              initial = false;
              return wrapper.getDebuggeeState();
            }
            if (DEBUG_TESTS) {
              System.out.println("Request for next stream state");
            }
            while (running) {
              running = wrapper.mainLoopStep();
              JUnit3Wrapper.DebuggeeState state = wrapper.getDebuggeeState();
              if (state != null && !state.frames.isEmpty()) {
                return state;
              }
              if (DEBUG_TESTS) {
                System.out.println("Continuing search for next stream state");
              }
            }
            if (DEBUG_TESTS) {
              System.out.println("Debuggee exited, no next stream state");
            }
            return null;
          }

          // When the set of streaming tests includes a Dalvik runtime it appears to interfere with
          // the state of other tests. In such a case, the below check fails and the 'state' of
          // the streams (both CF or DEX) appear to have become invalid.
          private boolean verifyStateLocation(JUnit3Wrapper.DebuggeeState state) {
            Location thisLocation = state.getLocation();
            Location procLocation =
                state.getMirror().getAllThreadFrames(state.threadId).get(0).getLocation();
            assert thisLocation.methodID == procLocation.methodID;
            return true;
          }
        });
  }

  protected final JUnit3Wrapper.Command run() {
    return new JUnit3Wrapper.Command.RunCommand();
  }

  protected final JUnit3Wrapper.Command breakpoint(MethodReference method) {
    return breakpoint(method.getHolderClass().getTypeName(), method.getMethodName());
  }

  protected final JUnit3Wrapper.Command breakpoint(String className, String methodName) {
    return breakpoint(className, methodName, null);
  }

  protected final JUnit3Wrapper.Command breakpoint(String className, String methodName, int line) {
    return breakpoint(className, methodName, null, line);
  }

  protected final JUnit3Wrapper.Command breakpoint(String className, String methodName,
      String methodSignature) {
    return breakpoint(className, methodName, methodSignature, FIRST_LINE);
  }

  protected final JUnit3Wrapper.Command breakpoint(String className, String methodName,
      String methodSignature, int line) {
    return new JUnit3Wrapper.Command.BreakpointCommand(className, methodName, methodSignature, line);
  }

  protected final JUnit3Wrapper.Command breakOnException(String className, String methodName,
      boolean caught, boolean uncaught) {
    return new JUnit3Wrapper.Command.BreakOnExceptionCommand(
        className, methodName, caught, uncaught);
  }

  protected final JUnit3Wrapper.Command stepOver() {
    return stepOver(DEFAULT_FILTER);
  }

  protected final JUnit3Wrapper.Command stepOver(StepFilter stepFilter) {
    return step(StepKind.OVER, stepFilter);
  }

  protected final JUnit3Wrapper.Command stepOut() {
    return stepOut(DEFAULT_FILTER);
  }

  protected final JUnit3Wrapper.Command stepOut(StepFilter stepFilter) {
    return step(StepKind.OUT, stepFilter);
  }

  protected final JUnit3Wrapper.Command stepInto() {
    return stepInto(DEFAULT_FILTER);
  }

  protected final JUnit3Wrapper.Command stepInto(StepFilter stepFilter) {
    return step(StepKind.INTO, stepFilter);
  }

  protected static List<Variable> getVisibleKotlinInlineVariables(
      JUnit3Wrapper.DebuggeeState debuggeeState) {
    return debuggeeState.getVisibleVariables().stream()
        .filter(v -> v.getName().matches("^\\$i\\$f\\$.*$")).collect(Collectors.toList());
  }

  public enum StepKind {
    INTO(StepDepth.INTO),
    OVER(StepDepth.OVER),
    OUT(StepDepth.OUT);

    private final byte jdwpValue;

    StepKind(byte jdwpValue) {
      this.jdwpValue = jdwpValue;
    }
  }

  public enum StepLevel {
    LINE(StepSize.LINE),
    INSTRUCTION(StepSize.MIN);

    private final byte jdwpValue;

    StepLevel(byte jdwpValue) {
      this.jdwpValue = jdwpValue;
    }
  }

  private JUnit3Wrapper.Command step(StepKind stepKind, StepFilter stepFilter) {
    return step(stepKind, StepLevel.LINE, stepFilter);
  }

  private JUnit3Wrapper.Command step(StepKind stepKind, StepLevel stepLevel,
      StepFilter stepFilter) {
    return new JUnit3Wrapper.Command.StepCommand(stepKind, stepLevel, stepFilter);
  }

  protected JUnit3Wrapper.Command stepUntil(StepKind stepKind, StepLevel stepLevel,
      Function<JUnit3Wrapper.DebuggeeState, Boolean> stepUntil) {
    return stepUntil(stepKind, stepLevel, stepUntil, DEFAULT_FILTER);
  }

  protected JUnit3Wrapper.Command stepUntil(StepKind stepKind, StepLevel stepLevel,
      Function<JUnit3Wrapper.DebuggeeState, Boolean> stepUntil, StepFilter stepFilter) {
    // We create an extension to the given step filter which will also check whether we need to
    // step again according to the given stepUntil function.
    StepFilter stepUntilFilter = new StepFilter() {
      @Override
      public List<String> getExcludedClasses() {
        return stepFilter.getExcludedClasses();
      }

      @Override
      public boolean skipLocation(JUnit3Wrapper.DebuggeeState debuggeeState, JUnit3Wrapper wrapper,
          JUnit3Wrapper.Command.StepCommand stepCommand) {
        if (stepFilter.skipLocation(debuggeeState, wrapper, stepCommand)) {
          return true;
        }
        if (stepUntil.apply(debuggeeState) == Boolean.FALSE) {
          // We did not reach the expected location so step again.
          wrapper.enqueueCommandFirst(stepCommand);
          return true;
        }
        return false;
      }
    };
    return new JUnit3Wrapper.Command.StepCommand(stepKind, stepLevel, stepUntilFilter);
  }

  protected final JUnit3Wrapper.Command checkLocal(String localName) {
    return inspect(t -> t.checkLocal(localName));
  }

  protected final JUnit3Wrapper.Command checkLocals(String... localNames) {
    return inspect(t -> {
      for (String str : localNames) {
        t.checkLocal(str);
      }
    });
  }

  protected final JUnit3Wrapper.Command checkLocal(String localName, Value expectedValue) {
    return inspect(t -> t.checkLocal(localName, expectedValue));
  }

  protected final JUnit3Wrapper.Command checkNoLocal(String localName) {
    return inspect(t -> t.checkNoLocal(localName));
  }

  protected final JUnit3Wrapper.Command checkNoLocals(String... localNames) {
    return inspect(t -> {
      for (String str : localNames) {
        t.checkNoLocal(str);
      }
    });
  }

  protected final JUnit3Wrapper.Command checkNoLocal() {
    return inspect(t -> {
      List<String> localNames = t.getLocalNames();
      Assert.assertTrue("Local variables: " + String.join(",", localNames), localNames.isEmpty());
    });
  }

  protected final JUnit3Wrapper.Command checkLine(int line) {
    return inspect(t -> t.checkLine(null, line));
  }

  protected final JUnit3Wrapper.Command checkLine(String sourceFile, int line) {
    return inspect(t -> t.checkLine(sourceFile, line));
  }

  protected final JUnit3Wrapper.Command checkInlineFrames(List<SignatureAndLine> expectedFrames) {
    return inspect(
        t -> {
          List<SignatureAndLine> actualFrames = t.getInlineFrames();
          Assert.assertEquals(expectedFrames.size(), actualFrames.size());
          for (int i = 0; i < expectedFrames.size(); ++i) {
            SignatureAndLine expectedFrame = expectedFrames.get(i);
            SignatureAndLine actualFrame = actualFrames.get(i);
            Assert.assertEquals(expectedFrame.signature, actualFrame.signature);
            Assert.assertEquals(expectedFrame.line, actualFrame.line);
          }
        });
  }

  protected final JUnit3Wrapper.Command checkMethod(String className, String methodName) {
    return checkMethod(className, methodName, null);
  }

  protected final JUnit3Wrapper.Command checkMethod(String className, String methodName,
      String methodSignature) {
    return inspect(t -> {
      Assert.assertEquals("Incorrect class name", className, t.getClassName());
      Assert.assertEquals("Incorrect method name", methodName, t.getMethodName());
      if (methodSignature != null) {
        Assert.assertEquals("Incorrect method signature", methodSignature,
            t.getMethodSignature());
      }
    });
  }

  protected final JUnit3Wrapper.Command checkStaticFieldClinitSafe(
      String className, String fieldName, String fieldSignature, Value expectedValue) {
    return inspect(t -> {
      // TODO(65148874): The current Art from AOSP master hangs when requesting static fields
      // when breaking in <clinit>. Last known good version is 7.0.0.
      Assume.assumeTrue(
          "Skipping test " + testName.getMethodName() + " because ART version is not supported",
          t.isCfRuntime() || ToolHelper.getDexVm().getVersion().isOlderThanOrEqual(Version.V7_0_0));
      checkStaticField(className, fieldName, fieldSignature, expectedValue);
    });
  }

  protected final JUnit3Wrapper.Command checkStaticField(
      String className, String fieldName, String fieldSignature, Value expectedValue) {
    return inspect(t -> {
      Value value = t.getStaticField(className, fieldName, fieldSignature);
      Assert.assertEquals("Incorrect value for static '" + className + "." + fieldName + "'",
          expectedValue, value);
    });
  }

  protected final JUnit3Wrapper.Command checkFieldOnThis(
      String fieldName, String fieldSignature, Value expectedValue) {
    return inspect(
        t -> {
          Value value = t.getFieldOnThis(fieldName, fieldSignature);
          Assert.assertEquals(
              "Incorrect value for field 'this." + fieldName + "'", expectedValue, value);
        });
  }

  protected final JUnit3Wrapper.Command inspect(Consumer<JUnit3Wrapper.DebuggeeState> inspector) {
    return t -> inspector.accept(t.debuggeeState);
  }

  protected final JUnit3Wrapper.Command conditional(
      Function<JUnit3Wrapper.DebuggeeState, List<JUnit3Wrapper.Command>> conditional) {
    return t -> subcommands(conditional.apply(t.debuggeeState)).perform(t);
  }

  protected final JUnit3Wrapper.Command subcommands(List<JUnit3Wrapper.Command> commands) {
    return t -> Lists.reverse(commands).forEach(t.commandsQueue::addFirst);
  }

  protected final JUnit3Wrapper.Command setLocal(String localName, Value newValue) {
    return new JUnit3Wrapper.Command.SetLocalCommand(localName, newValue);
  }

  protected final JUnit3Wrapper.Command getLocal(String localName, Consumer<Value> inspector) {
    return t -> inspector.accept(t.debuggeeState.getLocalValues().get(localName));
  }

  protected interface DebugTestRunner {
    void enqueueCommandFirst(JUnit3Wrapper.Command command);

    void runBare() throws Throwable;
  }

  @Ignore("Prevents Gradle from running the wrapper as a test.")
  public static class JUnit3Wrapper extends JDWPTestCase implements DebugTestRunner {

    private final String debuggeeClassName;

    // Initially, the runtime is suspended so we're ready to process commands.
    private State state = State.ProcessCommand;

    /**
     * Represents the context of the debuggee suspension. This is {@code null} when the debuggee is
     * not suspended.
     */
    private DebuggeeState debuggeeState = null;

    private final Deque<Command> commandsQueue;
    private final Translator translator;

    // Active event requests.
    private final Map<Integer, EventHandler> events = new TreeMap<>();

    private final DebugTestConfig config;

    /**
     * The Translator interface provides mapping between the class and method names and line numbers
     * found in the binary file and their original forms.
     *
     * <p>Terminology:
     *
     * <p>The term 'original' refers to the names and line numbers found in the original source
     * code. The term 'obfuscated' refers to the names and line numbers in the binary. Note that
     * they may not actually be obfuscated:
     *
     * <p>- The obfuscated class and method names can be identical to the original ones if
     * minification is disabled or they are 'keep' classes/methods. - The obfuscated line numbers
     * can be identical to the original ones if neither inlining nor line number remapping took
     * place.
     */
    private interface Translator {
      String getOriginalClassName(String obfuscatedClassName);

      String getOriginalClassNameForLine(
          String obfuscatedClassName, String obfuscatedMethodName, int obfuscatedLineNumber);

      String getOriginalMethodName(
          String obfuscatedClassName, String obfuscatedMethodName, String methodSignature);

      String getOriginalMethodNameForLine(
          String obfuscatedClassName,
          String obfuscatedMethodName,
          String methodSignature,
          int obfuscatedLineNumber);

      int getOriginalLineNumber(
          String obfuscatedClassName, String obfuscatedMethodName, int obfuscatedLineNumber);

      List<SignatureAndLine> getInlineFramesForLine(
          String obfuscatedClassName, String obfuscatedMethodName, int obfuscatedLineNumber);

      String getObfuscatedClassName(String originalClassName);

      String getObfuscatedMethodName(
          String originalClassName, String originalMethodName, String methodSignature);
    }

    private class IdentityTranslator implements Translator {

      @Override
      public String getOriginalClassName(String obfuscatedClassName) {
        return obfuscatedClassName;
      }

      @Override
      public String getOriginalClassNameForLine(
          String obfuscatedClassName, String obfuscatedMethodName, int obfuscatedLineNumber) {
        return obfuscatedClassName;
      }

      @Override
      public String getOriginalMethodName(
          String obfuscatedClassName, String obfuscatedMethodName, String methodSignature) {
        return obfuscatedMethodName;
      }

      @Override
      public String getOriginalMethodNameForLine(
          String obfuscatedClassName,
          String obfuscatedMethodName,
          String methodSignature,
          int obfuscatedLineNumber) {
        return obfuscatedMethodName;
      }

      @Override
      public int getOriginalLineNumber(
          String obfuscatedClassName, String obfuscatedMethodName, int obfuscatedLineNumber) {
        return obfuscatedLineNumber;
      }

      @Override
      public List<SignatureAndLine> getInlineFramesForLine(
          String obfuscatedClassName, String obfuscatedMethodName, int obfuscatedLineNumber) {
        return null;
      }

      @Override
      public String getObfuscatedClassName(String originalClassName) {
        return originalClassName;
      }

      @Override
      public String getObfuscatedMethodName(
          String originalClassName, String originalMethodName, String methodSignature) {
        return originalMethodName;
      }
    }

    private class ClassNameMapperTranslator extends IdentityTranslator {
      private final ClassNameMapper classNameMapper;

      public ClassNameMapperTranslator(ClassNameMapper classNameMapper) {
        this.classNameMapper = classNameMapper;
      }

      @Override
      public String getOriginalClassName(String obfuscatedClassName) {
        return classNameMapper.deobfuscateClassName(obfuscatedClassName);
      }

      private ClassNamingForNameMapper.MappedRange getMappedRangeForLine(
          String obfuscatedClassName, String obfuscatedMethodName, int obfuscatedLineNumber) {
        ClassNamingForNameMapper classNaming = classNameMapper.getClassNaming(obfuscatedClassName);
        if (classNaming == null) {
          return null;
        }
        ClassNamingForNameMapper.MappedRangesOfName ranges =
            classNaming.mappedRangesByRenamedName.get(obfuscatedMethodName);
        if (ranges == null) {
          return null;
        }
        return ranges.firstRangeForLine(obfuscatedLineNumber);
      }

      @Override
      public String getOriginalClassNameForLine(
          String obfuscatedClassName, String obfuscatedMethodName, int obfuscatedLineNumber) {
        ClassNamingForNameMapper.MappedRange range =
            getMappedRangeForLine(obfuscatedClassName, obfuscatedMethodName, obfuscatedLineNumber);
        if (range == null) {
          return obfuscatedClassName;
        }
        return range.signature.type;
      }

      @Override
      public String getOriginalMethodName(
          String obfuscatedClassName, String obfuscatedMethodName, String methodSignature) {
        MemberNaming memberNaming =
            getMemberNaming(obfuscatedClassName, obfuscatedMethodName, methodSignature);
        if (memberNaming == null) {
          return obfuscatedMethodName;
        }

        Signature originalSignature = memberNaming.getOriginalSignature();
        return originalSignature.name;
      }

      @Override
      public String getOriginalMethodNameForLine(
          String obfuscatedClassName,
          String obfuscatedMethodName,
          String methodSignature,
          int obfuscatedLineNumber) {
        ClassNamingForNameMapper.MappedRange range =
            getMappedRangeForLine(obfuscatedClassName, obfuscatedMethodName, obfuscatedLineNumber);
        if (range == null) {
          return obfuscatedMethodName;
        }
        return range.signature.name;
      }

      @Override
      public int getOriginalLineNumber(
          String obfuscatedClassName, String obfuscatedMethodName, int obfuscatedLineNumber) {
        ClassNamingForNameMapper.MappedRange range =
            getMappedRangeForLine(obfuscatedClassName, obfuscatedMethodName, obfuscatedLineNumber);
        if (range == null) {
          return obfuscatedLineNumber;
        }
        return range.getOriginalLineNumber(obfuscatedLineNumber);
      }

      @Override
      public List<SignatureAndLine> getInlineFramesForLine(
          String obfuscatedClassName, String obfuscatedMethodName, int obfuscatedLineNumber) {
        ClassNamingForNameMapper classNaming = classNameMapper.getClassNaming(obfuscatedClassName);
        if (classNaming == null) {
          return null;
        }
        ClassNamingForNameMapper.MappedRangesOfName ranges =
            classNaming.mappedRangesByRenamedName.get(obfuscatedMethodName);
        if (ranges == null) {
          return null;
        }
        List<MappedRange> mappedRanges = ranges.allRangesForLine(obfuscatedLineNumber);
        if (mappedRanges.isEmpty()) {
          return null;
        }
        List<SignatureAndLine> lines = new ArrayList<>(mappedRanges.size());
        for (MappedRange range : mappedRanges) {
          lines.add(
              new SignatureAndLine(
                  range.signature.toString(), range.getOriginalLineNumber(obfuscatedLineNumber)));
        }
        return lines;
      }

      @Override
      public String getObfuscatedClassName(String originalClassName) {
        // TODO(tamaskenez) Watch for inline methods (we can be in a different class).
        String obfuscatedClassName =
            classNameMapper.getObfuscatedToOriginalMapping().inverse.get(originalClassName);
        return obfuscatedClassName == null ? originalClassName : obfuscatedClassName;
      }

      @Override
      public String getObfuscatedMethodName(
          String originalClassName, String originalMethodName, String methodSignatureOrNull) {
        ClassNamingForNameMapper naming;
        String obfuscatedClassName =
            classNameMapper.getObfuscatedToOriginalMapping().inverse.get(originalClassName);
        if (obfuscatedClassName != null) {
          naming = classNameMapper.getClassNaming(obfuscatedClassName);
        } else {
          return originalMethodName;
        }

        if (methodSignatureOrNull == null) {
          List<MemberNaming> memberNamings = naming.lookupByOriginalName(originalMethodName);
          if (memberNamings.isEmpty()) {
            return originalMethodName;
          } else if (memberNamings.size() == 1) {
            return memberNamings.get(0).getRenamedName();
          } else
            throw new RuntimeException(
                String.format(
                    "Looking up method %s.%s without signature is ambiguous (%d candidates).",
                    originalClassName, originalMethodName, memberNamings.size()));
        } else {
          MethodSignature originalSignature =
              MethodSignature.fromSignature(originalMethodName, methodSignatureOrNull);
          MemberNaming memberNaming = naming.lookupByOriginalSignature(originalSignature);
          if (memberNaming == null) {
            return originalMethodName;
          }

          return memberNaming.getRenamedName();
        }
      }

      /** Assumes classNameMapper is valid. Return null if no member naming found. */
      private MemberNaming getMemberNaming(
          String obfuscatedClassName, String obfuscatedMethodName, String genericMethodSignature) {
        ClassNamingForNameMapper classNaming = classNameMapper.getClassNaming(obfuscatedClassName);
        if (classNaming == null) {
          return null;
        }

        MethodSignature renamedSignature =
            MethodSignature.fromSignature(obfuscatedMethodName, genericMethodSignature);
        return classNaming.lookup(renamedSignature);
      }
    }

    JUnit3Wrapper(
        DebugTestConfig config,
        String debuggeeClassName,
        List<Command> commands,
        ClassNameMapper classNameMapper) {
      this.config = config;
      this.debuggeeClassName = debuggeeClassName;
      this.commandsQueue = new ArrayDeque<>(commands);
      if (classNameMapper == null) {
        this.translator = new IdentityTranslator();
      } else {
        this.translator = new ClassNameMapperTranslator(classNameMapper);
      }
    }

    void prepareForStreaming() throws Exception {
      if (DEBUG_TESTS) {
        System.out.println("Preparing test for stream execution");
      }
      setUp();
    }

    @Override
    protected void runTest() throws Throwable {
      if (DEBUG_TESTS) {
        logWriter.println("Starts loop with " + commandsQueue.size() + " command(s) to process");
      }

      while (mainLoopStep()) {
        // Continue stepping until mainLoopStep exits with false.
      }

      if (config.mustProcessAllCommands()) {
        assertTrue(
            "All commands have NOT been processed for config: " + config, commandsQueue.isEmpty());
      }

      logWriter.println("Finish loop");
    }

    private boolean mainLoopStep() {
      if (DEBUG_TESTS) {
        logWriter.println("Loop on state " + state.name());
      }
      switch (state) {
        case ProcessCommand: {
          Command command = commandsQueue.poll();
          assert command != null;
          if (DEBUG_TESTS) {
            logWriter.println("Process command " + command.toString());
          }
          try {
            command.perform(this);
          } catch (TestErrorException e) {
            boolean ignoreException = false;
            if (config.isDexRuntime()
                && ToolHelper.getDexVm().getVersion().isOlderThanOrEqual(Version.V4_4_4)) {
              // Dalvik has flaky synchronization issue on shutdown. The workaround is to ignore
              // the exception if and only if we know that it's the final resume command.
              if (debuggeeState == null && commandsQueue.isEmpty()) {
                // We should receive the VMDeath event and transition to the Exit state here.
                processEvents();
                assert state == State.Exit;
                ignoreException = true;
              }
            }
            if (!ignoreException) {
              throw e;
            }
          }
          break;
        }
        case WaitForEvent:
          processEvents();
          break;
        case Exit:
          return false;
        default:
          throw new AssertionError();
      }
      return true;
    }

    @Override
    protected String getDebuggeeClassName() {
      return debuggeeClassName;
    }

    private enum State {
      /**
       * Process next command
       */
      ProcessCommand,
      /**
       * Wait for the next event
       */
      WaitForEvent,
      /**
       * The debuggee has exited
       */
      Exit
    }

    // We expect to have either a single event or two events with one being an installed breakpoint.
    private ParsedEvent getPrimaryEvent(ParsedEvent[] events) {
      assertTrue(events.length == 1 || events.length == 2);
      if (events.length == 1) {
        return events[0];
      }
      assertEquals(2, events.length);
      for (ParsedEvent event : events) {
        if (event.getEventKind() == EventKind.BREAKPOINT) {
          return event;
        }
      }
      fail("Expected breakpoint when receiving multiple events.");
      throw new Unreachable();
    }

    private void processEvents() {
      EventPacket eventPacket = getMirror().receiveEvent();
      ParsedEvent[] parsedEvents = ParsedEvent.parseEventPacket(eventPacket);
      if (DEBUG_TESTS) {
        logWriter.println("Received " + parsedEvents.length + " event(s)");
        for (int i = 0; i < parsedEvents.length; ++i) {
          String msg =
              String.format(
                  "#%d: %s (id=%d)",
                  i,
                  JDWPConstants.EventKind.getName(parsedEvents[i].getEventKind()),
                  parsedEvents[i].getRequestID());
          logWriter.println(msg);
        }
      }
      ParsedEvent parsedEvent = getPrimaryEvent(parsedEvents);
      byte eventKind = parsedEvent.getEventKind();
      int requestID = parsedEvent.getRequestID();

      if (eventKind == JDWPConstants.EventKind.VM_DEATH) {
        // Special event when debuggee is about to terminate.
        assertEquals(0, requestID);
        setState(State.Exit);
      } else {
        assert parsedEvent.getSuspendPolicy() == SuspendPolicy.ALL;

        // Capture the context of the event suspension.
        updateEventContext((EventThread) parsedEvent);

        if (DEBUG_TESTS && debuggeeState.getLocation() != null) {
          // Dump location
          String classSig = getMirror().getClassSignature(debuggeeState.getLocation().classID);
          String methodName = VmMirrorUtils
              .getMethodName(getMirror(), debuggeeState.getLocation().classID,
                  debuggeeState.getLocation().methodID);
          String methodSig = VmMirrorUtils
              .getMethodSignature(getMirror(), debuggeeState.getLocation().classID,
                  debuggeeState.getLocation().methodID);
          String msg =
              String.format(
                  "Suspended in %s#%s%s@0x%x",
                  classSig, methodName, methodSig, debuggeeState.getLocation().index);
          if (debuggeeState.getLocation().index >= 0) {
            msg += " (line " + debuggeeState.getLineNumber() + ")";
          }
          System.out.println(msg);
        }

        // Handle event.
        EventHandler eh = events.get(requestID);
        assert eh != null;
        eh.handle(this);
      }
    }

    @Override
    protected JPDATestOptions createTestOptions() {
      // Override properties to run debuggee with ART/Dalvik.
      class ArtTestOptions extends JPDATestOptions {

        ArtTestOptions(String[] debuggeePath) {
          // Set debuggee command-line.
          if (config.isDexRuntime()) {
            ArtCommandBuilder artCommandBuilder = new ArtCommandBuilder(ToolHelper.getDexVm());
            if (ToolHelper.getDexVm().getVersion().isNewerThan(DexVm.Version.V5_1_1)) {
              artCommandBuilder.appendArtOption("-Xcompiler-option");
              artCommandBuilder.appendArtOption("--debuggable");
            }
            if (ToolHelper.getDexVm().getVersion().isAtLeast(DexVm.Version.V9_0_0) &&
                ToolHelper.getDexVm().getVersion() != DexVm.Version.DEFAULT) {
              artCommandBuilder.appendArtOption("-XjdwpProvider:internal");
            }
            if (DEBUG_TESTS && ToolHelper.getDexVm().getVersion().isNewerThan(Version.V4_4_4)) {
              artCommandBuilder.appendArtOption("-verbose:jdwp");
            }
            setProperty("jpda.settings.debuggeeJavaPath", artCommandBuilder.build());
          }

          // Set debuggee classpath
          String debuggeeClassPath = String.join(File.pathSeparator, debuggeePath);
          setProperty("jpda.settings.debuggeeClasspath", debuggeeClassPath);

          // Force to localhost (required for continuous testing configuration). Use port '0'
          // for automatic selection (required when tests are executed in parallel).
          setProperty("jpda.settings.transportAddress", "127.0.0.1:0");

          // Set verbosity
          setProperty("jpda.settings.verbose", Boolean.toString(DEBUG_TESTS));
        }
      }
      return new ArtTestOptions(
          config.getPaths().stream().map(Path::toString).toArray(String[]::new));
    }

    public void enqueueCommandFirst(Command command) {
      commandsQueue.addFirst(command);
    }

    public void enqueueCommandsFirst(List<Command> commands) {
      for (int i = commands.size() - 1; i >= 0; --i) {
        enqueueCommandFirst(commands.get(i));
      }
    }

    //
    // Inspection
    //

    public interface FrameInspector {
      long getFrameId();
      Location getLocation();

      int getLineNumber();

      List<SignatureAndLine> getInlineFrames();

      String getSourceFile();
      String getClassName();
      String getClassSignature();
      String getMethodName();
      String getMethodSignature();

      // Locals

      List<Variable> getVisibleVariables();

      /**
       * Returns the names of all local variables visible at the current location
       */
      List<String> getLocalNames();

      /**
       * Returns the values of all locals visible at the current location.
       */
      Map<String, Value> getLocalValues();
      void checkNoLocal(String localName);
      void checkLocal(String localName);
      void checkLocal(String localName, Value expectedValue);

      void setLocal(String localName, Value newValue);

      void checkLine(String sourceFile, int line);
    }

    public static class DebuggeeState implements FrameInspector {

      private class DebuggeeFrame implements FrameInspector {

        private final JUnit3Wrapper wrapper;
        private final long frameId;
        private final Location location;
        private final Translator translator;

        public DebuggeeFrame(
            JUnit3Wrapper wrapper, long frameId, Location location, Translator translator) {
          this.wrapper = wrapper;
          this.frameId = frameId;
          this.location = location;
          this.translator = translator;
        }

        public long getFrameId() {
          return frameId;
        }

        public Location getLocation() {
          return location;
        }

        private int getObfuscatedLineNumber() {
          Location location = getLocation();
          ReplyPacket reply = getMirror().getLineTable(location.classID, location.methodID);
          if (reply.getErrorCode() != 0) {
            return -1;
          }

          long startCodeIndex = reply.getNextValueAsLong();
          long endCodeIndex = reply.getNextValueAsLong();
          int lines = reply.getNextValueAsInt();
          int line = -1;
          long previousLineCodeIndex = -1;
          for (int i = 0; i < lines; ++i) {
            long currentLineCodeIndex = reply.getNextValueAsLong();
            int currentLineNumber = reply.getNextValueAsInt();

            // Code indices are in ascending order.
            assert currentLineCodeIndex >= startCodeIndex;
            assert currentLineCodeIndex <= endCodeIndex;
            assert currentLineCodeIndex >= previousLineCodeIndex;
            previousLineCodeIndex = currentLineCodeIndex;

            if (location.index >= currentLineCodeIndex) {
              line = currentLineNumber;
            } else {
              break;
            }
          }
          return line;
        }

        public int getLineNumber() {
          return translator.getOriginalLineNumber(
              getObfuscatedClassName(), getObfuscatedMethodName(), getObfuscatedLineNumber());
        }

        public List<SignatureAndLine> getInlineFrames() {
          return translator.getInlineFramesForLine(
              getObfuscatedClassName(), getObfuscatedMethodName(), getObfuscatedLineNumber());
        }

        public String getSourceFile() {
          // TODO(shertz) support JSR-45
          Location location = getLocation();
          CommandPacket sourceFileCommand = new CommandPacket(
              JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
              JDWPCommands.ReferenceTypeCommandSet.SourceFileCommand);
          sourceFileCommand.setNextValueAsReferenceTypeID(location.classID);
          ReplyPacket replyPacket = getMirror().performCommand(sourceFileCommand);
          if (replyPacket.getErrorCode() != 0) {
            return null;
          } else {
            return replyPacket.getNextValueAsString();
          }
        }

        @Override
        public List<Variable> getVisibleVariables() {
          // Get variable table and keep only variables visible at this location.
          Location frameLocation = getLocation();
          return getVariables(getMirror(), frameLocation.classID, frameLocation.methodID).stream()
              .filter(v -> inScope(frameLocation.index, v))
              .collect(Collectors.toList());
        }

        public List<String> getLocalNames() {
          return getVisibleVariables().stream().map(Variable::getName).collect(Collectors.toList());
        }

        @Override
        public Map<String, Value> getLocalValues() {
          return JUnit3Wrapper.getVariablesAt(mirror, location)
              .stream()
              .collect(
                  Collectors.toMap(
                      Variable::getName,
                      v -> {
                        // Get local value
                        CommandPacket commandPacket =
                            new CommandPacket(
                                JDWPCommands.StackFrameCommandSet.CommandSetID,
                                JDWPCommands.StackFrameCommandSet.GetValuesCommand);
                        commandPacket.setNextValueAsThreadID(getThreadId());
                        commandPacket.setNextValueAsFrameID(getFrameId());
                        commandPacket.setNextValueAsInt(1);
                        commandPacket.setNextValueAsInt(v.getSlot());
                        commandPacket.setNextValueAsByte(v.getTag());
                        ReplyPacket replyPacket = getMirror().performCommand(commandPacket);
                        int valuesCount = replyPacket.getNextValueAsInt();
                        assert valuesCount == 1;
                        return replyPacket.getNextValueAsValue();
                      }));
        }

        private String convertCurrentLocationToString() {
          return getSourceFile() + ":" + getLineNumber()
              + " (pc 0x" + Long.toHexString(location.index) + ")";
        }

        private void failNoLocal(String localName) {
          String locationString = convertCurrentLocationToString();
          Assert.fail("expected local '" + localName + "' is not present at " + locationString);
        }

        private void checkIncorrectLocal(String localName, Value expected, Value actual) {
          if (expected.equals(actual)) {
            return;
          }
          String locationString = convertCurrentLocationToString();
          Assert.fail(
              "Incorrect value for local '"
                  + localName
                  + "' at "
                  + locationString
                  + ", expected "
                  + expected
                  + ", actual "
                  + actual);
        }

        @Override
        public void checkNoLocal(String localName) {
          Optional<Variable> localVar = getVariableAt(mirror, getLocation(), localName);
          if (localVar.isPresent()) {
            String locationString = convertCurrentLocationToString();
            Assert.fail("unexpected local '" + localName + "' is present at " + locationString);
          }
        }

        public void checkLocal(String localName) {
          Optional<Variable> localVar = getVariableAt(mirror, getLocation(), localName);
          if (!localVar.isPresent()) {
            failNoLocal(localName);
          }
        }

        public void checkLocal(String localName, Value expectedValue) {
          Optional<Variable> localVar = getVariableAt(mirror, getLocation(), localName);
          if (!localVar.isPresent()) {
            failNoLocal(localName);
          }

          // Get value
          CommandPacket commandPacket = new CommandPacket(
              JDWPCommands.StackFrameCommandSet.CommandSetID,
              JDWPCommands.StackFrameCommandSet.GetValuesCommand);
          commandPacket.setNextValueAsThreadID(getThreadId());
          commandPacket.setNextValueAsFrameID(getFrameId());
          commandPacket.setNextValueAsInt(1);
          commandPacket.setNextValueAsInt(localVar.get().getSlot());
          commandPacket.setNextValueAsByte(localVar.get().getTag());
          ReplyPacket replyPacket = getMirror().performCommand(commandPacket);
          int valuesCount = replyPacket.getNextValueAsInt();
          assert valuesCount == 1;
          Value localValue = replyPacket.getNextValueAsValue();

          checkIncorrectLocal(localName, expectedValue, localValue);
        }

        @Override
        public void setLocal(String localName, Value newValue) {
          Optional<Variable> localVar = getVariableAt(mirror, getLocation(), localName);
          Assert.assertTrue("No local '" + localName + "'", localVar.isPresent());

          CommandPacket setValues =
              new CommandPacket(
                  StackFrameCommandSet.CommandSetID, StackFrameCommandSet.SetValuesCommand);
          setValues.setNextValueAsThreadID(getThreadId());
          setValues.setNextValueAsFrameID(getFrameId());
          setValues.setNextValueAsInt(1);
          setValues.setNextValueAsInt(localVar.get().getSlot());
          setValues.setNextValueAsValue(newValue);
          ReplyPacket replyPacket = mirror.performCommand(setValues);
          wrapper.checkReplyPacket(replyPacket, "StackFrame.SetValues");
        }

        @Override
        public void checkLine(String sourceFile, int line) {
          sourceFile = sourceFile != null ? sourceFile : getSourceFile();
          if (!Objects.equals(sourceFile, getSourceFile()) || line != getLineNumber()) {
            String locationString = convertCurrentLocationToString();
            Assert.fail(
                "Incorrect line at " + locationString + ", expected " + sourceFile + ":" + line);
          }
        }

        /**
         * Return class name, as found in the binary. If it has not been obfuscated (minified) it's
         * identical to the original class name. Otherwise, it's the obfuscated one.
         */
        private String getObfuscatedClassName() {
          String classSignature = getClassSignature();
          assert classSignature.charAt(0) == 'L';
          // Remove leading 'L' and trailing ';'
          classSignature = classSignature.substring(1, classSignature.length() - 1);
          // Return fully qualified name
          return classSignature.replace('/', '.');
        }

        public String getClassName() {
          return translator.getOriginalClassName(getObfuscatedClassName());
        }

        public String getClassSignature() {
          Location location = getLocation();
          return getMirror().getClassSignature(location.classID);
        }

        // Return method name as found in the binary. Can be obfuscated (minified).
        private String getObfuscatedMethodName() {
          Location location = getLocation();
          return getMirror().getMethodName(location.classID, location.methodID);
        }

        // Return original method name.
        public String getMethodName() {
          return translator.getOriginalMethodName(
              getObfuscatedClassName(), getObfuscatedMethodName(), getMethodSignature());
        }

        public String getMethodSignature() {
          Location location = getLocation();
          CommandPacket command = new CommandPacket(ReferenceTypeCommandSet.CommandSetID,
              ReferenceTypeCommandSet.MethodsWithGenericCommand);
          command.setNextValueAsReferenceTypeID(location.classID);

          ReplyPacket reply = getMirror().performCommand(command);
          assert reply.getErrorCode() == Error.NONE;
          int methods = reply.getNextValueAsInt();

          for (int i = 0; i < methods; ++i) {
            long methodId = reply.getNextValueAsMethodID();
            reply.getNextValueAsString(); // skip name
            String methodSignature = reply.getNextValueAsString();
            reply.getNextValueAsString(); // skip generic signature
            reply.getNextValueAsInt();  // skip modifiers
            if (methodId == location.methodID) {
              return methodSignature;
            }
          }
          throw new AssertionError("No method info for the current location");
        }
      }

      private final DebugTestConfig config;
      private final VmMirror mirror;
      private final long threadId;
      private final List<DebuggeeFrame> frames;

      public DebuggeeState(
          DebugTestConfig config, VmMirror mirror, long threadId, List<DebuggeeFrame> frames) {
        this.config = config;
        this.mirror = mirror;
        this.threadId = threadId;
        this.frames = frames;
      }

      public DebugTestConfig getConfig() {
        return config;
      }

      public boolean isCfRuntime() {
        return getConfig().isCfRuntime();
      }

      public boolean isDexRuntime() {
        return getConfig().isDexRuntime();
      }

      public VmMirror getMirror() {
        return mirror;
      }

      public long getThreadId() {
        return threadId;
      }

      public int getFrameDepth() {
        return frames.size();
      }

      public FrameInspector getFrame(int index) {
        return frames.get(index);
      }

      public FrameInspector getTopFrame() {
        return getFrame(0);
      }

      @Override
      public long getFrameId() {
        return getTopFrame().getFrameId();
      }

      @Override
      public Location getLocation() {
        return frames.isEmpty() ? null : getTopFrame().getLocation();
      }

      @Override
      public void checkNoLocal(String localName) {
        getTopFrame().checkNoLocal(localName);
      }

      @Override
      public void checkLocal(String localName) {
        getTopFrame().checkLocal(localName);
      }

      @Override
      public void checkLocal(String localName, Value expectedValue) {
        getTopFrame().checkLocal(localName, expectedValue);
      }

      @Override
      public void setLocal(String localName, Value newValue) {
        getTopFrame().setLocal(localName, newValue);
      }

      @Override
      public void checkLine(String sourceFile, int line) {
        getTopFrame().checkLine(sourceFile, line);
      }

      @Override
      public int getLineNumber() {
        return getTopFrame().getLineNumber();
      }

      @Override
      public List<SignatureAndLine> getInlineFrames() {
        return getTopFrame().getInlineFrames();
      }

      @Override
      public String getSourceFile() {
        return getTopFrame().getSourceFile();
      }

      @Override
      public List<String> getLocalNames() {
        return getTopFrame().getLocalNames();
      }

      @Override
      public Map<String, Value> getLocalValues() {
        return getTopFrame().getLocalValues();
      }

      @Override
      public String getClassName() {
        return getTopFrame().getClassName();
      }

      @Override
      public String getClassSignature() {
        return getTopFrame().getClassSignature();
      }

      @Override
      public String getMethodName() {
        return getTopFrame().getMethodName();
      }

      @Override
      public String getMethodSignature() {
        return getTopFrame().getMethodSignature();
      }

      @Override
      public List<Variable> getVisibleVariables() {
        return getTopFrame().getVisibleVariables();
      }

      public Value getStaticField(String className, String fieldName, String fieldSignature) {
        String classSignature = DescriptorUtils.javaTypeToDescriptor(className);
        byte typeTag = TypeTag.CLASS;
        long classId = getMirror().getClassID(classSignature);
        Assert.assertFalse("No class named " + className + " found", classId == -1);

        // The class is available, lookup and read the field.
        long fieldId = findField(getMirror(), classId, fieldName, fieldSignature);
        return internalStaticField(getMirror(), classId, fieldId);
      }

      public Value getFieldOnThis(String fieldName, String fieldSignature) {
        long thisObjectId = getMirror().getThisObject(getThreadId(), getFrameId());
        long classId = getMirror().getReferenceType(thisObjectId);
        // TODO(zerny): Search supers too. This will only get the field if directly on the class.
        long fieldId = findField(getMirror(), classId, fieldName, fieldSignature);
        return internalInstanceField(getMirror(), thisObjectId, fieldId);
      }

      private long findField(VmMirror mirror, long classId, String fieldName,
          String fieldSignature) {

        boolean withGenericSignature = true;
        CommandPacket commandPacket = new CommandPacket(ReferenceTypeCommandSet.CommandSetID,
            ReferenceTypeCommandSet.FieldsWithGenericCommand);
        commandPacket.setNextValueAsReferenceTypeID(classId);
        ReplyPacket replyPacket = mirror.performCommand(commandPacket);
        if (replyPacket.getErrorCode() != Error.NONE) {
          // Retry with older command ReferenceType.Fields.
          withGenericSignature = false;
          commandPacket.setCommand(ReferenceTypeCommandSet.FieldsCommand);
          replyPacket = mirror.performCommand(commandPacket);
          assert replyPacket.getErrorCode() == Error.NONE;
        }

        int fieldsCount = replyPacket.getNextValueAsInt();
        LongList matchingFieldIds = new LongArrayList();
        for (int i = 0; i < fieldsCount; ++i) {
          long currentFieldId = replyPacket.getNextValueAsFieldID();
          String currentFieldName = replyPacket.getNextValueAsString();
          String currentFieldSignature = replyPacket.getNextValueAsString();
          if (withGenericSignature) {
            replyPacket.getNextValueAsString(); // Skip generic signature.
          }
          replyPacket.getNextValueAsInt(); // Skip modifiers.

          // Filter fields based on name (and signature if there is).
          if (fieldName.equals(currentFieldName)) {
            if (fieldSignature == null || fieldSignature.equals(currentFieldSignature)) {
              matchingFieldIds.add(currentFieldId);
            }
          }
        }
        Assert.assertTrue(replyPacket.isAllDataRead());

        Assert.assertFalse("No field named " + fieldName + " found", matchingFieldIds.isEmpty());
        // There must be only one matching field.
        Assert.assertEquals("More than 1 field found: please specify a signature", 1,
            matchingFieldIds.size());
        return matchingFieldIds.getLong(0);
      }

      private static Value internalStaticField(VmMirror mirror, long classId, long fieldId) {
        CommandPacket commandPacket =
            new CommandPacket(
                ReferenceTypeCommandSet.CommandSetID, ReferenceTypeCommandSet.GetValuesCommand);
        commandPacket.setNextValueAsReferenceTypeID(classId);
        commandPacket.setNextValueAsInt(1);
        commandPacket.setNextValueAsFieldID(fieldId);
        ReplyPacket replyPacket = mirror.performCommand(commandPacket);
        assert replyPacket.getErrorCode() == Error.NONE;

        int fieldsCount = replyPacket.getNextValueAsInt();
        assert fieldsCount == 1;
        Value result = replyPacket.getNextValueAsValue();
        Assert.assertTrue(replyPacket.isAllDataRead());
        return result;
      }
    }

    private static Value internalInstanceField(VmMirror mirror, long objectId, long fieldId) {
      CommandPacket commandPacket =
          new CommandPacket(
              ObjectReferenceCommandSet.CommandSetID, ObjectReferenceCommandSet.GetValuesCommand);
      commandPacket.setNextValueAsObjectID(objectId);
      commandPacket.setNextValueAsInt(1);
      commandPacket.setNextValueAsFieldID(fieldId);
      ReplyPacket replyPacket = mirror.performCommand(commandPacket);
      assert replyPacket.getErrorCode() == Error.NONE;

      int fieldsCount = replyPacket.getNextValueAsInt();
      assert fieldsCount == 1;
      Value result = replyPacket.getNextValueAsValue();
      Assert.assertTrue(replyPacket.isAllDataRead());
      return result;
    }

    public static Optional<Variable> getVariableAt(VmMirror mirror, Location location,
        String localName) {
      return getVariablesAt(mirror, location).stream()
          .filter(v -> localName.equals(v.getName()))
          .findFirst();
    }

    protected static boolean inScope(long index, Variable var) {
      long varStart = var.getCodeIndex();
      long varEnd = varStart + var.getLength();
      return index >= varStart && index < varEnd;
    }

    private static List<Variable> getVariablesAt(VmMirror mirror, Location location) {
      // Get variable table and keep only variables visible at this location.
      return getVariables(mirror, location.classID, location.methodID).stream()
          .filter(v -> inScope(location.index, v))
          .collect(Collectors.toList());
    }

    private static List<Variable> getVariables(VmMirror mirror, long classID, long methodID) {
      List<Variable> list = mirror.getVariableTable(classID, methodID);
      return list != null ? list : Collections.emptyList();
    }

    private void setState(State state) {
      this.state = state;
    }

    public DebuggeeState getDebuggeeState() {
      return debuggeeState;
    }

    private void updateEventContext(EventThread event) {
      final long threadId = event.getThreadID();
      final List<JUnit3Wrapper.DebuggeeState.DebuggeeFrame> frames = new ArrayList<>();
      debuggeeState = new DebuggeeState(config, getMirror(), threadId, frames);

      // ART returns an error if we ask for frames when there is none. Workaround by asking the
      // frame count first.
      int frameCount = getMirror().getFrameCount(threadId);
      if (frameCount > 0) {
        ReplyPacket replyPacket = getMirror().getThreadFrames(threadId, 0, frameCount);
        int number = replyPacket.getNextValueAsInt();
        assertEquals(frameCount, number);

        for (int i = 0; i < frameCount; ++i) {
          long frameId = replyPacket.getNextValueAsFrameID();
          Location location = replyPacket.getNextValueAsLocation();
          frames.add(debuggeeState.new DebuggeeFrame(this, frameId, location, translator));
        }
        assertAllDataRead(replyPacket);
      }
    }

    private VmMirror getMirror() {
      return debuggeeWrapper.vmMirror;
    }

    private void resume() {
      debuggeeState = null;
      getMirror().resume();
      setState(State.WaitForEvent);
    }

    private LongList getMethodCodeIndex(long classId, long breakpointMethodId, int lineToSearch) {
      LongList pcs = new LongArrayList();
      ReplyPacket replyPacket = getMirror().getLineTable(classId, breakpointMethodId);
      checkReplyPacket(replyPacket, "Failed to get method line table");
      long start = replyPacket.getNextValueAsLong(); // start
      replyPacket.getNextValueAsLong(); // end
      int linesCount = replyPacket.getNextValueAsInt();
      if (linesCount == 0) {
        if (lineToSearch == FIRST_LINE) {
          // There is no line table but we are not looking for a specific line. Therefore just
          // set the breakpoint on the 1st instruction.
          pcs.add(start);
        } else {
          pcs.add(-1L);
        }
      } else {
        if (lineToSearch == FIRST_LINE) {
          // Read only the 1st line because code indices are in ascending order
          pcs.add(replyPacket.getNextValueAsLong());
        } else {
          for (int entry = 0; entry < linesCount; entry++) {
            long pc = replyPacket.getNextValueAsLong();
            long lineNumber = replyPacket.getNextValueAsInt();
            if (lineNumber == lineToSearch) {
              pcs.add(pc);
            }
          }
        }
      }
      return pcs;
    }

    //
    // Command processing
    //
    public interface Command {

      void perform(JUnit3Wrapper testBase);

      class RunCommand implements Command {

        @Override
        public void perform(JUnit3Wrapper testBase) {
          testBase.resume();
        }

        @Override
        public String toString() {
          return "run";
        }
      }

      // Break on exceptions thrown in className.methodName.
      class BreakOnExceptionCommand implements Command {
        private static final int ALL_EXCEPTIONS = 0;
        private final String className;
        private final String methodName;
        private final boolean caught;
        private final boolean uncaught;

        public BreakOnExceptionCommand(
            String className, String methodName, boolean caught, boolean uncaught) {
          this.className = className;
          this.methodName = methodName;
          this.caught = caught;
          this.uncaught = uncaught;
        }

        @Override
        public void perform(JUnit3Wrapper testBase) {
          ReplyPacket replyPacket =
              testBase.getMirror().setException(ALL_EXCEPTIONS, caught, uncaught);
          assert replyPacket.getErrorCode() == Error.NONE;
          int breakpointId = replyPacket.getNextValueAsInt();
          testBase.events.put(
              Integer.valueOf(breakpointId),
              new BreakOnExceptionHandler(className, methodName));
        }

        @Override
        public String toString() {
          return "breakOnException";
        }
      }

      class BreakpointCommand implements Command {

        private final String className;
        private final String methodName;
        private final String methodSignature;
        private boolean requestedClassPrepare = false;
        private int line;

        public BreakpointCommand(String className, String methodName,
            String methodSignature, int line) {
          assert className != null;
          assert methodName != null;
          this.className = className;
          this.methodName = methodName;
          this.methodSignature = methodSignature;
          this.line = line;
        }

        @Override
        public void perform(JUnit3Wrapper testBase) {
          VmMirror mirror = testBase.getMirror();
          String obfuscatedClassName = testBase.translator.getObfuscatedClassName(className);
          String classSignature = getClassSignature(obfuscatedClassName);
          byte typeTag = TypeTag.CLASS;
          long classId = mirror.getClassID(classSignature);
          if (classId == -1) {
            // Is it an interface ?
            classId = mirror.getInterfaceID(classSignature);
            typeTag = TypeTag.INTERFACE;
          }
          if (classId == -1) {
            // The class is not ready yet. Request a CLASS_PREPARE to delay the installation of the
            // breakpoint.
            assert !requestedClassPrepare : "Already requested class prepare";
            requestedClassPrepare = true;
            ReplyPacket replyPacket = mirror.setClassPrepared(obfuscatedClassName);
            final int classPrepareRequestId = replyPacket.getNextValueAsInt();
            testBase.events.put(
                Integer.valueOf(classPrepareRequestId),
                wrapper -> {
                  // Remove the CLASS_PREPARE
                  wrapper.events.remove(Integer.valueOf(classPrepareRequestId));
                  wrapper
                      .getMirror()
                      .clearEvent(JDWPConstants.EventKind.CLASS_PREPARE, classPrepareRequestId);

                  // Breakpoint then resume.
                  wrapper.enqueueCommandsFirst(
                      Arrays.asList(
                          BreakpointCommand.this, new JUnit3Wrapper.Command.RunCommand()));

                  // Set wrapper ready to process next command.
                  wrapper.setState(State.ProcessCommand);
                });
          } else {
            // The class is available: lookup the method then set the breakpoint.
            String obfuscatedMethodName =
                testBase.translator.getObfuscatedMethodName(className, methodName, methodSignature);
            long breakpointMethodId =
                findMethod(mirror, classId, obfuscatedMethodName, methodSignature);
            LongList pcs = testBase.getMethodCodeIndex(classId, breakpointMethodId, line);
            for (long pc : pcs) {
              Assert.assertTrue("No code in method", pc >= 0);
              ReplyPacket replyPacket = testBase.getMirror().setBreakpoint(
                  new Location(typeTag, classId, breakpointMethodId, pc), SuspendPolicy.ALL);
              assert replyPacket.getErrorCode() == Error.NONE;
              int breakpointId = replyPacket.getNextValueAsInt();
              testBase.events.put(Integer.valueOf(breakpointId), new DefaultEventHandler());
            }
          }
        }

        private static long findMethod(VmMirror mirror, long classId, String methodName,
            String methodSignature) {

          boolean withGenericSignature = true;
          CommandPacket commandPacket = new CommandPacket(ReferenceTypeCommandSet.CommandSetID,
              ReferenceTypeCommandSet.MethodsWithGenericCommand);
          commandPacket.setNextValueAsReferenceTypeID(classId);
          ReplyPacket replyPacket = mirror.performCommand(commandPacket);
          if (replyPacket.getErrorCode() != Error.NONE) {
            // Retry with older command ReferenceType.Methods
            withGenericSignature = false;
            commandPacket.setCommand(ReferenceTypeCommandSet.MethodsCommand);
            replyPacket = mirror.performCommand(commandPacket);
            assert replyPacket.getErrorCode() == Error.NONE;
          }

          int methodsCount = replyPacket.getNextValueAsInt();
          LongSet matchingMethodIds = new LongOpenHashSet();
          for (int i = 0; i < methodsCount; ++i) {
            long currentMethodId = replyPacket.getNextValueAsMethodID();
            String currentMethodName = replyPacket.getNextValueAsString();
            String currentMethodSignature = replyPacket.getNextValueAsString();
            if (withGenericSignature) {
              replyPacket.getNextValueAsString(); // skip generic signature
            }
            replyPacket.getNextValueAsInt(); // skip modifiers

            // Filter methods based on name (and signature if there is).
            if (methodName.equals(currentMethodName)) {
              if (methodSignature == null || methodSignature.equals(currentMethodSignature)) {
                matchingMethodIds.add(currentMethodId);
              }
            }
          }
          Assert.assertTrue(replyPacket.isAllDataRead());

          Assert
              .assertFalse("No method named " + methodName + " found", matchingMethodIds.isEmpty());
          // There must be only one matching method
          Assert.assertEquals("More than 1 method found: please specify a signature", 1,
              matchingMethodIds.size());
          return matchingMethodIds.iterator().nextLong();
        }

        @Override
        public String toString() {
          return String.format(
              "breakpoint class=%s method=%s signature=%s line=%s",
              className, methodName, methodSignature, line);
        }
      }

      class StepCommand implements Command {

        private final StepKind stepDepth;
        private final StepLevel stepSize;
        private final StepFilter stepFilter;

        public StepCommand(StepKind stepDepth, StepLevel stepSize, StepFilter stepFilter) {
          this.stepDepth = stepDepth;
          this.stepSize = stepSize;
          this.stepFilter = stepFilter;
        }

        @Override
        public void perform(JUnit3Wrapper testBase) {
          long threadId = testBase.getDebuggeeState().getThreadId();
          int stepRequestID;
          {
            EventBuilder eventBuilder = Event.builder(EventKind.SINGLE_STEP, SuspendPolicy.ALL);
            eventBuilder.setStep(threadId, stepSize.jdwpValue, stepDepth.jdwpValue);
            stepFilter.getExcludedClasses().forEach(eventBuilder::setClassExclude);
            ReplyPacket replyPacket = testBase.getMirror().setEvent(eventBuilder.build());
            stepRequestID = replyPacket.getNextValueAsInt();
            testBase.assertAllDataRead(replyPacket);
          }
          testBase.events.put(stepRequestID, new StepEventHandler(this, stepRequestID, stepFilter));

          // Resume all threads.
          testBase.resume();
        }

        @Override
        public String toString() {
          return String.format("step %s/%s", JDWPConstants.StepDepth.getName(stepDepth.jdwpValue),
              JDWPConstants.StepSize.getName(stepSize.jdwpValue));
        }
      }

      class SetLocalCommand implements Command {

        private final String localName;
        private final Value newValue;

        public SetLocalCommand(String localName, Value newValue) {
          this.localName = localName;
          this.newValue = newValue;
        }

        @Override
        public void perform(JUnit3Wrapper testBase) {
          Optional<Variable> localVar =
              getVariableAt(testBase.getMirror(), testBase.debuggeeState.getLocation(), localName);
          Assert.assertTrue("No local '" + localName + "'", localVar.isPresent());

          CommandPacket setValues = new CommandPacket(StackFrameCommandSet.CommandSetID,
              StackFrameCommandSet.SetValuesCommand);
          setValues.setNextValueAsThreadID(testBase.getDebuggeeState().getThreadId());
          setValues.setNextValueAsFrameID(testBase.getDebuggeeState().getFrameId());
          setValues.setNextValueAsInt(1);
          setValues.setNextValueAsInt(localVar.get().getSlot());
          setValues.setNextValueAsValue(newValue);
          ReplyPacket replyPacket = testBase.getMirror().performCommand(setValues);
          testBase.checkReplyPacket(replyPacket, "StackFrame.SetValues");
        }
      }
    }

    //
    // Event handling
    //
    private interface EventHandler {

      void handle(JUnit3Wrapper testBase);
    }

    private static class DefaultEventHandler implements EventHandler {

      @Override
      public void handle(JUnit3Wrapper testBase) {
        testBase.setState(State.ProcessCommand);
      }
    }

    private static class BreakOnExceptionHandler extends DefaultEventHandler {
      private final String className;
      private final String methodName;

      BreakOnExceptionHandler(String className, String methodName) {
        this.className = className;
        this.methodName = methodName;
      }

      @Override
      public void handle(JUnit3Wrapper testBase) {
        boolean inMethod =
            testBase.getDebuggeeState().getTopFrame().getMethodName().equals(methodName);
        boolean inClass =
            testBase.getDebuggeeState().getTopFrame().getClassName().equals(className);
        if (!(inClass && inMethod)) {
          // Not the right place, continue until the next exception.
          testBase.enqueueCommandFirst(new JUnit3Wrapper.Command.RunCommand());
        }
        testBase.setState(State.ProcessCommand);
      }
    }

    private static class StepEventHandler extends DefaultEventHandler {

      private final JUnit3Wrapper.Command.StepCommand stepCommand;
      private final int stepRequestID;
      private final StepFilter stepFilter;

      private StepEventHandler(
          JUnit3Wrapper.Command.StepCommand stepCommand,
          int stepRequestID,
          StepFilter stepFilter) {
        this.stepCommand = stepCommand;
        this.stepRequestID = stepRequestID;
        this.stepFilter = stepFilter;
      }

      @Override
      public void handle(JUnit3Wrapper testBase) {
        // Clear step event.
        testBase.getMirror().clearEvent(EventKind.SINGLE_STEP, stepRequestID);
        testBase.events.remove(Integer.valueOf(stepRequestID));

        // Let the filtering happen.
        // Note: we don't need to know whether the location was skipped or not because we are
        // going to process the next command(s) in the queue anyway.
        stepFilter.skipLocation(testBase.getDebuggeeState(), testBase, stepCommand);

        super.handle(testBase);
      }
    }

  }

  //
  // Step filtering
  //

  interface StepFilter {

    /**
     * Provides a list of class name to be skipped when single stepping. This can be a fully
     * qualified name (like java.lang.String) or a subpackage (like java.util.*).
     */
    List<String> getExcludedClasses();

    /**
     * Indicates whether the given location must be skipped.
     */
    boolean skipLocation(JUnit3Wrapper.DebuggeeState debuggeeState, JUnit3Wrapper wrapper,
        JUnit3Wrapper.Command.StepCommand stepCommand);

    /**
     * A {@link StepFilter} that does not filter anything.
     */
    class NoStepFilter implements StepFilter {

      @Override
      public List<String> getExcludedClasses() {
        return Collections.emptyList();
      }

      @Override
      public boolean skipLocation(JUnit3Wrapper.DebuggeeState debuggeeState, JUnit3Wrapper wrapper,
          JUnit3Wrapper.Command.StepCommand stepCommand) {
        return false;
      }
    }

    /**
     * A {@link StepFilter} that matches the default behavior of IntelliJ regarding single
     * stepping.
     */
    class IntelliJStepFilter implements StepFilter {
      // This is the value specified by JDWP in documentation of ReferenceType.Methods command.
      private static final int SYNTHETIC_FLAG = 0xF0000000;

      @Override
      public List<String> getExcludedClasses() {
        return ImmutableList.of(
            "com.sun.*",
            "java.*",
            "javax.*",
            "org.omg.*",
            "sun.*",
            "jdk.internal.*",
            "junit.*",
            "com.intellij.rt.*",
            "com.yourkit.runtime.*",
            "com.springsource.loaded.*",
            "org.springsource.loaded.*",
            "javassist.*",
            "org.apache.webbeans.*",
            "com.ibm.ws.*",
            "kotlin.*");
      }

      @Override
      public boolean skipLocation(JUnit3Wrapper.DebuggeeState debuggeeState, JUnit3Wrapper wrapper,
          JUnit3Wrapper.Command.StepCommand stepCommand) {
        VmMirror mirror = debuggeeState.getMirror();
        Location location = debuggeeState.getLocation();
        // Skip synthetic methods.
        if (isLambdaMethod(mirror, location)) {
          // Lambda methods are synthetic but we do want to stop there.
          if (DEBUG_TESTS) {
            System.out.println("NOT skipping lambda implementation method");
          }
          return false;
        }
        if (isInLambdaClass(mirror, location)) {
          // Lambda classes must be skipped since they are only wrappers around lambda code.
          if (DEBUG_TESTS) {
            System.out.println("Skipping lambda class wrapper method");
          }
          wrapper.enqueueCommandFirst(stepCommand);
          return true;
        }
        if (isSyntheticMethod(mirror, location)) {
          if (DEBUG_TESTS) {
            System.out.println("Skipping synthetic method");
          }
          wrapper.enqueueCommandFirst(stepCommand);
          return true;
        }
        if (isClassLoader(mirror, location)) {
          if (DEBUG_TESTS) {
            System.out.println("Skipping class loader");
          }
          wrapper.enqueueCommandFirst(
              new JUnit3Wrapper.Command.StepCommand(StepKind.OUT, StepLevel.LINE, this));
          return true;
        }
        return false;
      }

      private static boolean isClassLoader(VmMirror mirror, Location location) {
        final long classLoaderClassID = mirror.getClassID("Ljava/lang/ClassLoader;");
        assert classLoaderClassID != -1;
        long classID = location.classID;
        while (classID != 0) {
          if (classID == classLoaderClassID) {
            return true;
          }
          classID = mirror.getSuperclassId(classID);
        }
        return false;
      }

      private static boolean isSyntheticMethod(VmMirror mirror, Location location) {
        // We must gather the modifiers of the method. This is only possible using
        // ReferenceType.Methods command which gather information about all methods in a class.
        Method[] methods = mirror.getMethods(location.classID);
        for (Method method : methods) {
          if (method.getMethodID() == location.methodID &&
              ((method.getModBits() & SYNTHETIC_FLAG) != 0)) {
            return true;
          }
        }
        return false;
      }

      private static boolean isInLambdaClass(VmMirror mirror, Location location) {
        String classSig = mirror.getClassSignature(location.classID);
        return classSig.contains("$$Lambda$");
      }

      private static boolean isLambdaMethod(VmMirror mirror, Location location) {
        String methodName = mirror.getMethodName(location.classID, location.methodID);
        return methodName.startsWith("lambda$");
      }
    }

    /**
     * IntelliJ derived step filter that also skips all android runtime specific libraries.
     */
    class AndroidRuntimeStepFilter extends IntelliJStepFilter {

      @Override
      public List<String> getExcludedClasses() {
        return ImmutableList.<String>builder()
            .addAll(super.getExcludedClasses())
            .add("libcore.*")
            .add("dalvik.*")
            .add("com.android.dex.*") // Android 6.0.1 - 7.0.0 use this for reflection.
            .build();
      }
    }
  }
}
