// Path: src/main/java/org/tsers/junitquest/finder/MyClassWriter.java
// public class MyClassWriter extends ClassWriter {
//     private ClassLoader classLoader;
// 
//     public MyClassWriter(int i, ClassLoader loader) {
//         super(i);
//         this.classLoader = loader;
//     }
// 
//     @Override
//     protected String getCommonSuperClass(final String type1, final String type2) {
//         Class c, d;
//         try {
//             c = classLoader.loadClass(type1.replace('/', '.'));
//             d = classLoader.loadClass(type2.replace('/', '.'));
//         } catch (Exception e) {
//             throw new RuntimeException(e.toString());
//         }
//         if (c.isAssignableFrom(d)) {
//             return type1;
//         }
//         if (d.isAssignableFrom(c)) {
//             return type2;
//         }
//         if (c.isInterface() || d.isInterface()) {
//             return "java/lang/Object";
//         } else {
//             do {
//                 c = c.getSuperclass();
//             } while (!c.isAssignableFrom(d));
//             return c.getName().replace('.', '/');
//         }
//     }
// }


import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.*;
import org.tsers.junitquest.finder.MyClassWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;

            InstanceHelper.setClassLoader(urlClassLoader);
            InstanceHelper.init(urlClassLoader, bytecodeLocation);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static List<MethodNode> getMethodNodes() {
        return methodNodes;
    }

    public static MethodNode getMethodNode(String packagename, String methodName, String methodDesc) {
        MethodNode node = getMethodNodes().stream()
                .filter(m -> m.name.equals(methodName) && m.desc.equals(methodDesc))
                .findAny()
                .orElseThrow(() -> new RuntimeException("Cannot find methodnode for: " + methodName));
        return node;
    }

    private static byte[] getInstrumentedByteCode(InputStream classStream) throws IOException {
        ClassReader classReader = new ClassReader(classStream);
        ClassNode classNode = new ClassNode();
        classReader.accept(classNode, 0);


        methodNodes.addAll(classNode.methods);
        ((List<MethodNode>) classNode.methods).stream()
                .forEach(m -> instrumentMethod(m));
        ClassWriter classWriter;
// Path: src/main/java/org/tsers/junitquest/finder/MyClassWriter.java
// public class MyClassWriter extends ClassWriter {
//     private ClassLoader classLoader;
// 
//     public MyClassWriter(int i, ClassLoader loader) {
//         super(i);
//         this.classLoader = loader;
//     }
// 
//     @Override
//     protected String getCommonSuperClass(final String type1, final String type2) {
//         Class c, d;
//         try {
//             c = classLoader.loadClass(type1.replace('/', '.'));
//             d = classLoader.loadClass(type2.replace('/', '.'));
//         } catch (Exception e) {
//             throw new RuntimeException(e.toString());
//         }
//         if (c.isAssignableFrom(d)) {
//             return type1;
//         }
//         if (d.isAssignableFrom(c)) {
//             return type2;
//         }
//         if (c.isInterface() || d.isInterface()) {
//             return "java/lang/Object";
//         } else {
//             do {
//                 c = c.getSuperclass();
//             } while (!c.isAssignableFrom(d));
//             return c.getName().replace('.', '/');
//         }
//     }
// }


// Path: src/main/java/org/tsers/junitquest/Instrumenter.java
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.*;
import org.tsers.junitquest.finder.MyClassWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;


            InstanceHelper.setClassLoader(urlClassLoader);
            InstanceHelper.init(urlClassLoader, bytecodeLocation);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static List<MethodNode> getMethodNodes() {
        return methodNodes;
    }

    public static MethodNode getMethodNode(String packagename, String methodName, String methodDesc) {
        MethodNode node = getMethodNodes().stream()
                .filter(m -> m.name.equals(methodName) && m.desc.equals(methodDesc))
                .findAny()
                .orElseThrow(() -> new RuntimeException("Cannot find methodnode for: " + methodName));
        return node;
    }

    private static byte[] getInstrumentedByteCode(InputStream classStream) throws IOException {
        ClassReader classReader = new ClassReader(classStream);
        ClassNode classNode = new ClassNode();
        classReader.accept(classNode, 0);


        methodNodes.addAll(classNode.methods);
        ((List<MethodNode>) classNode.methods).stream()
                .forEach(m -> instrumentMethod(m));
        ClassWriter classWriter;
        classWriter = new MyClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES, urlClassLoader);