// Path: src/main/java/io/jvoid/instrumentation/provider/spock/RunFeatureMethodInstrumenter.java
// public class RunFeatureMethodInstrumenter implements MethodInstrumenter {
// 
//     @Override
//     public void instrument(CtMethod method) throws CannotCompileException {
//         // Right now is only called for the runFeature method
//         StringBuilder sb = new StringBuilder(1024);
//         // Get the String identifier of the spec
//         sb.append("String featureId = currentFeature.getFeatureMethod().getDescription().toString();\n");
//         sb.append(JVoidInstrumentationHelperHolder.helperGetterRef() + ".beginTest(featureId);\n");
//         sb.append("if (!" + JVoidInstrumentationHelperHolder.helperGetterRef() + ".wasTestRelatedCodeModified(featureId)) {\n");
//         sb.append("    supervisor.featureSkipped(currentFeature); return;\n");
//         sb.append("}\n");
//         method.insertBefore(sb.toString());
//     }
// 
//     @Override
//     public boolean shouldInstrument(CtMethod ctMethod) {
//         return true;
//     }
// 
// }
// 
// Path: src/main/java/io/jvoid/instrumentation/provider/spock/SpockInstrumentationProvider.java
// public class SpockInstrumentationProvider implements InstrumentationProvider {
// 
//     private MethodInstrumenter runFeatureMethodInstrumenter;
// 
//     @Inject
//     public SpockInstrumentationProvider(RunFeatureMethodInstrumenter runFeatureMethodInstrumenter) {
//         this.runFeatureMethodInstrumenter = runFeatureMethodInstrumenter;
//     }
// 
//     @Override
//     public boolean matches(CtClass ctClass) {
//         return ctClass.getName().contains("org.spockframework.runtime.BaseSpecRunner");
//     }
// 
//     @Override
//     public List<ClassHandler> getClassHandlers(CtClass ctClass) {
//         return Collections.emptyList();
//     }
// 
//     @Override
//     public List<MethodInstrumenter> getMethodInstrumenters(CtMethod ctMethod) {
//         if (ctMethod.getName().equals("runFeature")) {
//             return Collections.singletonList(runFeatureMethodInstrumenter);
//         }
//         return Collections.emptyList();
//     }
// 
// }
// 
// Path: src/test/java/io/jvoid/test/AbstractJVoidTest.java
// @UseModules({ JVoidModule.class })
// @RunWith(JVoidTestRunner.class)
// public abstract class AbstractJVoidTest {
// 
//     protected static final String DEFAULT_TEST_CONFIGURATION_FILE = "./src/test/resources/test-jvoid.config";
// 
//     private static ThreadLocal<Long> currentExecutionId = new ThreadLocal<>(); // Parallel tests?
// 
//     protected static final ClassPool classPool;
// 
//     @Inject
//     protected MetadataDatabase metadataDatabase;
// 
//     @Inject
//     protected JVoidInstrumentationHelper instrumentationHelper;
// 
//     @Inject
//     protected ExecutionsRepository executionsRepository;
// 
//     @Inject
//     protected JVoidExecutionContext jvoidExecutionContext;
// 
//     static {
//         // See ClassPool JavaDoc for memory consumption issues
//         ClassPool.doPruning = true;
//         classPool = ClassPool.getDefault();
//     }
// 
//     @Before
//     public void setUp() throws Exception {
//         // Make sure the database is initialized
//         metadataDatabase.startup();
// 
//         // Makes sure that the database is clean, then restarts it to apply the migrations.
//         // To be sure that each test runs in its own clean db environment.
//         // TODO: Can this be more elegant?
//         DbUtils.executeUpdate(metadataDatabase, "DROP ALL OBJECTS");
//         metadataDatabase.shutdown();
//         metadataDatabase.startup();
// 
//         currentExecutionId.set(0L);
//     }
// 
//     @After
//     public void tearDown() {
//         metadataDatabase.shutdown();
//         JVoidInstrumentationHelperHolder.getInstance().set(instrumentationHelper);
//     }
// 
//     /*
//      * Utility methods for current JExecution
//      */
//     protected Long getCurrentExecutionId() {
//         return currentExecutionId.get();
//     }
// 
//     protected synchronized JExecution setupCurrentExecution() {
//         return setupCurrentExecution(null);
//     }
// 
//     protected synchronized JExecution setupCurrentExecution(Long timestamp) {
//         JExecution currentExecution = new JExecution();
//         currentExecution.setTimestamp(timestamp == null ? System.currentTimeMillis() : timestamp);
//         currentExecution = executionsRepository.add(currentExecution);
//         currentExecutionId.set(currentExecution.getId());
//         jvoidExecutionContext.setCurrentExecution(currentExecution);
//         return currentExecution;
//     }
// }


import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.google.inject.Inject;
import io.jvoid.instrumentation.provider.spock.RunFeatureMethodInstrumenter;
import io.jvoid.instrumentation.provider.spock.SpockInstrumentationProvider;
import io.jvoid.test.AbstractJVoidTest;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
package io.jvoid.test.instrumentation.provider.spock;





public class SpockInstrumentationProviderTest extends AbstractJVoidTest {

    @Inject
    private RunFeatureMethodInstrumenter runFeatureMethodInstrumenter;

    private SpockInstrumentationProvider spockProvider;

    private CtClass ctBaseSpecRunner;
    private CtClass ctParameterizedSpecRunner;

    @Override
    @Before
    public void setUp() throws Exception {
        super.setUp();
        ctBaseSpecRunner = classPool.get("org.spockframework.runtime.BaseSpecRunner");
        ctParameterizedSpecRunner = classPool
                .get("org.spockframework.runtime.ParameterizedSpecRunner");

// Path: src/main/java/io/jvoid/instrumentation/provider/spock/RunFeatureMethodInstrumenter.java
// public class RunFeatureMethodInstrumenter implements MethodInstrumenter {
// 
//     @Override
//     public void instrument(CtMethod method) throws CannotCompileException {
//         // Right now is only called for the runFeature method
//         StringBuilder sb = new StringBuilder(1024);
//         // Get the String identifier of the spec
//         sb.append("String featureId = currentFeature.getFeatureMethod().getDescription().toString();\n");
//         sb.append(JVoidInstrumentationHelperHolder.helperGetterRef() + ".beginTest(featureId);\n");
//         sb.append("if (!" + JVoidInstrumentationHelperHolder.helperGetterRef() + ".wasTestRelatedCodeModified(featureId)) {\n");
//         sb.append("    supervisor.featureSkipped(currentFeature); return;\n");
//         sb.append("}\n");
//         method.insertBefore(sb.toString());
//     }
// 
//     @Override
//     public boolean shouldInstrument(CtMethod ctMethod) {
//         return true;
//     }
// 
// }
// 
// Path: src/main/java/io/jvoid/instrumentation/provider/spock/SpockInstrumentationProvider.java
// public class SpockInstrumentationProvider implements InstrumentationProvider {
// 
//     private MethodInstrumenter runFeatureMethodInstrumenter;
// 
//     @Inject
//     public SpockInstrumentationProvider(RunFeatureMethodInstrumenter runFeatureMethodInstrumenter) {
//         this.runFeatureMethodInstrumenter = runFeatureMethodInstrumenter;
//     }
// 
//     @Override
//     public boolean matches(CtClass ctClass) {
//         return ctClass.getName().contains("org.spockframework.runtime.BaseSpecRunner");
//     }
// 
//     @Override
//     public List<ClassHandler> getClassHandlers(CtClass ctClass) {
//         return Collections.emptyList();
//     }
// 
//     @Override
//     public List<MethodInstrumenter> getMethodInstrumenters(CtMethod ctMethod) {
//         if (ctMethod.getName().equals("runFeature")) {
//             return Collections.singletonList(runFeatureMethodInstrumenter);
//         }
//         return Collections.emptyList();
//     }
// 
// }
// 
// Path: src/test/java/io/jvoid/test/AbstractJVoidTest.java
// @UseModules({ JVoidModule.class })
// @RunWith(JVoidTestRunner.class)
// public abstract class AbstractJVoidTest {
// 
//     protected static final String DEFAULT_TEST_CONFIGURATION_FILE = "./src/test/resources/test-jvoid.config";
// 
//     private static ThreadLocal<Long> currentExecutionId = new ThreadLocal<>(); // Parallel tests?
// 
//     protected static final ClassPool classPool;
// 
//     @Inject
//     protected MetadataDatabase metadataDatabase;
// 
//     @Inject
//     protected JVoidInstrumentationHelper instrumentationHelper;
// 
//     @Inject
//     protected ExecutionsRepository executionsRepository;
// 
//     @Inject
//     protected JVoidExecutionContext jvoidExecutionContext;
// 
//     static {
//         // See ClassPool JavaDoc for memory consumption issues
//         ClassPool.doPruning = true;
//         classPool = ClassPool.getDefault();
//     }
// 
//     @Before
//     public void setUp() throws Exception {
//         // Make sure the database is initialized
//         metadataDatabase.startup();
// 
//         // Makes sure that the database is clean, then restarts it to apply the migrations.
//         // To be sure that each test runs in its own clean db environment.
//         // TODO: Can this be more elegant?
//         DbUtils.executeUpdate(metadataDatabase, "DROP ALL OBJECTS");
//         metadataDatabase.shutdown();
//         metadataDatabase.startup();
// 
//         currentExecutionId.set(0L);
//     }
// 
//     @After
//     public void tearDown() {
//         metadataDatabase.shutdown();
//         JVoidInstrumentationHelperHolder.getInstance().set(instrumentationHelper);
//     }
// 
//     /*
//      * Utility methods for current JExecution
//      */
//     protected Long getCurrentExecutionId() {
//         return currentExecutionId.get();
//     }
// 
//     protected synchronized JExecution setupCurrentExecution() {
//         return setupCurrentExecution(null);
//     }
// 
//     protected synchronized JExecution setupCurrentExecution(Long timestamp) {
//         JExecution currentExecution = new JExecution();
//         currentExecution.setTimestamp(timestamp == null ? System.currentTimeMillis() : timestamp);
//         currentExecution = executionsRepository.add(currentExecution);
//         currentExecutionId.set(currentExecution.getId());
//         jvoidExecutionContext.setCurrentExecution(currentExecution);
//         return currentExecution;
//     }
// }


// Path: src/test/java/io/jvoid/test/instrumentation/provider/spock/SpockInstrumentationProviderTest.java
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.google.inject.Inject;
import io.jvoid.instrumentation.provider.spock.RunFeatureMethodInstrumenter;
import io.jvoid.instrumentation.provider.spock.SpockInstrumentationProvider;
import io.jvoid.test.AbstractJVoidTest;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;

package io.jvoid.test.instrumentation.provider.spock;





public class SpockInstrumentationProviderTest extends AbstractJVoidTest {

    @Inject
    private RunFeatureMethodInstrumenter runFeatureMethodInstrumenter;

    private SpockInstrumentationProvider spockProvider;

    private CtClass ctBaseSpecRunner;
    private CtClass ctParameterizedSpecRunner;

    @Override
    @Before
    public void setUp() throws Exception {
        super.setUp();
        ctBaseSpecRunner = classPool.get("org.spockframework.runtime.BaseSpecRunner");
        ctParameterizedSpecRunner = classPool
                .get("org.spockframework.runtime.ParameterizedSpecRunner");

        spockProvider = new SpockInstrumentationProvider(runFeatureMethodInstrumenter);