// Path: src/main/java/io/disassemble/asm/visitor/flow/FlowQueryResult.java
// public class FlowQueryResult {
// 
//     private final FlowQuery query;
//     private final List<BasicInstruction> instructions;
// 
//     public FlowQueryResult(FlowQuery query, List<BasicInstruction> instructions) {
//         this.query = query;
//         this.instructions = instructions;
//     }
// 
//     /**
//      * Finds the BasicInstruction with the given name.
//      *
//      * @param name The name to search for.
//      * @return The BasicInstruction with the given name.
//      */
//     public Optional<BasicInstruction> findBasicInstruction(String name) {
//         for (int i = 0; i < instructions.size(); i++) {
//             String nodeName = query.nameAt(i);
//             if (nodeName != null && nodeName.equals(name)) {
//                 return Optional.ofNullable(instructions.get(i));
//             }
//         }
//         return Optional.empty();
//     }
// 
//     /**
//      * Finds the AbstractInsnNode with the given name.
//      *
//      * @param name The name to search for.
//      * @return The AbstractInsnNode with the given name.
//      */
//     public Optional<AbstractInsnNode> findInstruction(String name) {
//         Optional<BasicInstruction> insn = findBasicInstruction(name);
//         return (insn.flatMap(basicInstruction -> Optional.ofNullable(basicInstruction.insn)));
//     }
// 
//     /**
//      * Gets a map of the named instructions from the FlowQuery.
//      *
//      * @return A map of the named instructions from the FlowQuery.
//      */
//     public Map<String, AbstractInsnNode> namedInstructions() {
//         Map<String, AbstractInsnNode> instructions = new HashMap<>();
//         for (int i = 0; i < this.instructions.size(); i++) {
//             String nodeName = query.nameAt(i);
//             if (nodeName != null) {
//                 instructions.put(nodeName, this.instructions.get(i).insn);
//             }
//         }
//         return instructions;
//     }
// }


import io.disassemble.asm.ClassMethod;
import io.disassemble.asm.visitor.flow.FlowQuery;
import io.disassemble.asm.visitor.flow.FlowQueryResult;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @author Tyler Sedlar
 * @since 2/1/16
 */
public class Debugger {

    private static final String TEST_CLASS_NAME = "Sample";

    private static final Map<String, ClassMethod> methods = new HashMap<>();

    @BeforeClass
    public static void setup() {
        ClassScanner.scanClassPath(
                cn -> cn.name.equals(TEST_CLASS_NAME),
                cm -> methods.put(cm.key(), cm)
        );
    }

    @Test
    public void testControlFlowGraph() {
        methods.values().forEach(cm -> {
            if (cm.name().contains("<")) {
                return;
            }
            if (cm.name().contains("cfg")) {
                try {
                    long start = System.nanoTime();
                    cm.cfg().ifPresent(cfg -> {
                        cfg.execution().print(1);
//                        cfg.printBasicBlocks();
// Path: src/main/java/io/disassemble/asm/visitor/flow/FlowQueryResult.java
// public class FlowQueryResult {
// 
//     private final FlowQuery query;
//     private final List<BasicInstruction> instructions;
// 
//     public FlowQueryResult(FlowQuery query, List<BasicInstruction> instructions) {
//         this.query = query;
//         this.instructions = instructions;
//     }
// 
//     /**
//      * Finds the BasicInstruction with the given name.
//      *
//      * @param name The name to search for.
//      * @return The BasicInstruction with the given name.
//      */
//     public Optional<BasicInstruction> findBasicInstruction(String name) {
//         for (int i = 0; i < instructions.size(); i++) {
//             String nodeName = query.nameAt(i);
//             if (nodeName != null && nodeName.equals(name)) {
//                 return Optional.ofNullable(instructions.get(i));
//             }
//         }
//         return Optional.empty();
//     }
// 
//     /**
//      * Finds the AbstractInsnNode with the given name.
//      *
//      * @param name The name to search for.
//      * @return The AbstractInsnNode with the given name.
//      */
//     public Optional<AbstractInsnNode> findInstruction(String name) {
//         Optional<BasicInstruction> insn = findBasicInstruction(name);
//         return (insn.flatMap(basicInstruction -> Optional.ofNullable(basicInstruction.insn)));
//     }
// 
//     /**
//      * Gets a map of the named instructions from the FlowQuery.
//      *
//      * @return A map of the named instructions from the FlowQuery.
//      */
//     public Map<String, AbstractInsnNode> namedInstructions() {
//         Map<String, AbstractInsnNode> instructions = new HashMap<>();
//         for (int i = 0; i < this.instructions.size(); i++) {
//             String nodeName = query.nameAt(i);
//             if (nodeName != null) {
//                 instructions.put(nodeName, this.instructions.get(i).insn);
//             }
//         }
//         return instructions;
//     }
// }


// Path: src/test/java/Debugger.java
import io.disassemble.asm.ClassMethod;
import io.disassemble.asm.visitor.flow.FlowQuery;
import io.disassemble.asm.visitor.flow.FlowQueryResult;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.HashMap;
import java.util.List;
import java.util.Map;



/**
 * @author Tyler Sedlar
 * @since 2/1/16
 */
public class Debugger {

    private static final String TEST_CLASS_NAME = "Sample";

    private static final Map<String, ClassMethod> methods = new HashMap<>();

    @BeforeClass
    public static void setup() {
        ClassScanner.scanClassPath(
                cn -> cn.name.equals(TEST_CLASS_NAME),
                cm -> methods.put(cm.key(), cm)
        );
    }

    @Test
    public void testControlFlowGraph() {
        methods.values().forEach(cm -> {
            if (cm.name().contains("<")) {
                return;
            }
            if (cm.name().contains("cfg")) {
                try {
                    long start = System.nanoTime();
                    cm.cfg().ifPresent(cfg -> {
                        cfg.execution().print(1);
//                        cfg.printBasicBlocks();
                        List<FlowQueryResult> results = cfg.execution().query(