diff --git a/jadx-core/src/test/java/jadx/NotYetImplemented.java b/jadx-core/src/test/java/jadx/NotYetImplemented.java new file mode 100644 index 000000000..299f0d279 --- /dev/null +++ b/jadx-core/src/test/java/jadx/NotYetImplemented.java @@ -0,0 +1,24 @@ +package jadx; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Indicates a test which is known to fail. + * + *

This would cause a failure to be considered as success and a success as failure, + * with the benefit of updating the related issue when it has been resolved even unintentionally.

+ * + *

To have an effect, the test class must be annotated with: + * + * + * @ExtendWith(NotYetImplementedExtension.class) + * + *

+ */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD}) +public @interface NotYetImplemented { +} diff --git a/jadx-core/src/test/java/jadx/NotYetImplementedExtension.java b/jadx-core/src/test/java/jadx/NotYetImplementedExtension.java new file mode 100644 index 000000000..2a2ab2977 --- /dev/null +++ b/jadx-core/src/test/java/jadx/NotYetImplementedExtension.java @@ -0,0 +1,39 @@ +package jadx; + +import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.Set; + +import org.junit.jupiter.api.extension.AfterTestExecutionCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.TestExecutionExceptionHandler; + +public class NotYetImplementedExtension implements AfterTestExecutionCallback, TestExecutionExceptionHandler { + + private Set knownFailedMethods = new HashSet<>(); + + @Override + public void handleTestExecutionException(ExtensionContext context, Throwable throwable) throws Throwable { + if (!isNotYetImplemented(context)) { + throw throwable; + } + knownFailedMethods.add(context.getTestMethod().get()); + } + + @Override + public void afterTestExecution(ExtensionContext context) throws Exception { + if (!knownFailedMethods.contains(context.getTestMethod().get()) + && isNotYetImplemented(context) + && !context.getExecutionException().isPresent()) { + throw new AssertionError("Test " + + context.getTestClass().get().getName() + '.' + context.getTestMethod().get().getName() + + " is marked as @NotYetImplemented, but passes!"); + } + } + + private static boolean isNotYetImplemented(ExtensionContext context) { + return context.getTestMethod().get().getAnnotation(NotYetImplemented.class) != null + || context.getTestClass().get().getAnnotation(NotYetImplemented.class) != null; + } + +}