remove manual tests and add validator interface/rsapi validator

This commit is contained in:
Lucwousin
2019-10-29 01:17:01 +01:00
parent 9ff4a8516c
commit 633e6dc0e6
9 changed files with 109 additions and 128 deletions

View File

@@ -9,7 +9,6 @@ import com.openosrs.injector.injectors.MixinInjector;
import com.openosrs.injector.injectors.RSApiInjector;
import com.openosrs.injector.injectors.raw.ClearColorBuffer;
import com.openosrs.injector.injectors.raw.DrawAfterWidgets;
import com.openosrs.injector.injectors.raw.HidePlayerAttacks;
import com.openosrs.injector.injectors.raw.Occluder;
import com.openosrs.injector.injectors.raw.RasterizerHook;
import com.openosrs.injector.injectors.raw.RenderDraw;
@@ -69,7 +68,7 @@ public class Injection extends InjectData implements InjectTaskHandler
// inject(new HidePlayerAttacks(this));
new RSApiValidator(this).validate();
new InjectorValidator(this).validate();
}
public void save(File outputJar) throws IOException
@@ -91,9 +90,17 @@ public class Injection extends InjectData implements InjectTaskHandler
log.lifecycle("{} {}", name, injector.getCompletionMsg());
if (!injector.validate())
if (injector instanceof Validator)
validate((Validator) injector);
}
private void validate(Validator validator) throws Injexception
{
throw new Injexception(String.format("%s failed validation", name));
final String name = validator.getName();
if (!validator.validate())
{
throw new Injexception(name + " failed validation");
}
}

View File

@@ -0,0 +1,78 @@
package com.openosrs.injector;
import com.openosrs.injector.injection.InjectData;
import com.openosrs.injector.rsapi.RSApi;
import static com.openosrs.injector.rsapi.RSApi.API_BASE;
import com.openosrs.injector.rsapi.RSApiClass;
import com.openosrs.injector.rsapi.RSApiMethod;
import net.runelite.asm.ClassFile;
import net.runelite.asm.pool.Class;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
public class InjectorValidator implements Validator
{
private static final Logger log = Logging.getLogger(InjectorValidator.class);
private static final String OK = "OK", ERROR = "ERROR", WTF = "WTF";
private final InjectData inject;
private int missing = 0, okay = 0, wtf = 0;
InjectorValidator(InjectData inject)
{
this.inject = inject;
}
public boolean validate()
{
final RSApi rsApi = inject.getRsApi();
for (ClassFile cf : inject.getVanilla())
{
for (Class intf : cf.getInterfaces())
{
if (intf.getName().startsWith(API_BASE))
{
continue;
}
RSApiClass apiC = rsApi.findClass(intf.getName());
if (apiC == null)
{
log.error("{} is rs api type implemented by {} but it doesn't exist in rsapi. wtf", intf, cf.getPoolClass());
++wtf;
continue;
}
check(cf, apiC);
}
}
String status = wtf > 0 ? WTF : missing > 0 ? ERROR : OK;
log.info("RSApiValidator completed. Status [{}] {} overridden methods, {} missing", status, okay, missing);
// valid, ref to static final field
return status == OK;
}
private void check(ClassFile clazz, RSApiClass apiClass)
{
for (RSApiMethod apiMethod : apiClass)
{
if (apiMethod.isSynthetic() || apiMethod.isDefault())
{
continue;
}
if (clazz.findMethodDeep(apiMethod.getName(), apiMethod.getSignature()) == null)
{
log.warn("Class {} implements interface {} but doesn't implement {}",
clazz.getPoolClass(), apiClass.getClazz(), apiMethod.getMethod());
++missing;
}
else
{
++okay;
}
}
}
}

View File

@@ -1,37 +0,0 @@
package com.openosrs.injector;
import com.openosrs.injector.injection.InjectData;
import com.openosrs.injector.rsapi.RSApi;
import com.openosrs.injector.rsapi.RSApiClass;
import com.openosrs.injector.rsapi.RSApiMethod;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.internal.impldep.aQute.libg.cryptography.RSA;
public class RSApiValidator
{
private static final Logger log = Logging.getLogger(RSApiValidator.class);
private final InjectData inject;
public RSApiValidator(InjectData inject)
{
this.inject = inject;
}
public boolean validate() throws Injexception
{
RSApi rsApi = inject.getRsApi();
for (RSApiClass apiClass : rsApi)
{
for (RSApiMethod apiMethod : apiClass)
{
if (!apiMethod.isInjected())
if (!apiMethod.isSynthetic())
if (inject.toVanilla(inject.toDeob(apiClass.getName())).findMethod(apiMethod.getName(), apiMethod.getSignature()) == null)
log.warn("{} not injected", apiMethod.getMethod());
}
}
return false;
}
}

View File

@@ -0,0 +1,13 @@
package com.openosrs.injector;
import net.runelite.asm.Named;
public interface Validator extends Named
{
boolean validate();
default String getName()
{
return this.getClass().getSimpleName();
}
}

View File

@@ -413,11 +413,6 @@ public class InjectHook extends AbstractInjector
}
}
public String getName()
{
return super.getName();
}
@AllArgsConstructor
static class HookInfo
{

View File

@@ -1,22 +1,15 @@
package com.openosrs.injector.injectors;
import com.openosrs.injector.Injexception;
import net.runelite.asm.Named;
public interface Injector
public interface Injector extends Named
{
/**
* Where all the injection should be done
*/
void inject() throws Injexception;
/**
* Should return `true` if injection was succesful, `false` otherwise.
*/
default boolean validate()
{
return true;
}
/**
* Get a name the injector is going to be referred to in logging
*/

View File

@@ -38,4 +38,9 @@ public class RSApiMethod implements Annotated, Named
{
return (accessFlags & Opcodes.ACC_SYNTHETIC) != 0;
}
public boolean isDefault()
{
return (accessFlags & (Opcodes.ACC_ABSTRACT | Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC)) == 1;
}
}

View File

@@ -1,47 +0,0 @@
import com.openosrs.injector.rsapi.RSApi;
import com.openosrs.injector.rsapi.RSApiClass;
import com.openosrs.injector.rsapi.RSApiClassVisitor;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.junit.Ignore;
import org.junit.Test;
import org.objectweb.asm.ClassReader;
public class RSApiTest
{
private final RSApi api = new RSApi();
@Test
@Ignore
public void test() throws IOException
{
loadAndAdd("/net/runelite/rs/api/RSTest.class");
loadAndAdd("/net/runelite/rs/api/RSInterface.class");
api.init();
List<RSApiClass> classes = api.getClasses();
assert classes.size() == 2;
RSApiClass clazz = api.findClass("net/runelite/rs/api/RSTest");
assert clazz != null;
assert clazz.getMethods().size() == 4;
}
private void loadAndAdd(String path) throws IOException
{
List<RSApiClass> classes = api.getClasses();
try (InputStream is = RSApiTest.class.getResourceAsStream(path))
{
ClassReader reader = new ClassReader(is);
RSApiClass apiClass = new RSApiClass();
reader.accept(
new RSApiClassVisitor(apiClass),
ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES
);
classes.add(apiClass);
}
}
}

View File

@@ -1,26 +0,0 @@
import com.openosrs.injector.InjectPlugin;
import com.openosrs.injector.Injection;
import com.openosrs.injector.injection.InjectTaskHandler;
import java.io.File;
import org.gradle.api.Project;
import org.gradle.api.file.FileTree;
import org.gradle.testfixtures.ProjectBuilder;
import org.junit.Test;
public class TTest
{
private static final File VAN = new File("C:\\Users\\Lucas\\.gradle\\caches\\modules-2\\files-2.1\\net.runelite.rs\\vanilla\\184\\1bdb54d90d696598a8ee5ff793155482970180a\\vanilla-184.jar");
private static final Project project = ProjectBuilder.builder().withProjectDir(new File("C:\\Users\\Lucas\\IdeaProjects\\runelite")).build();
private static final FileTree API = project.zipTree("/runescape-api/build/libs/runescape-api-1.5.37-SNAPSHOT.jar"),
DEOB = project.zipTree("/runescape-client/build/libs/rs-client-1.5.37-SNAPSHOT.jar"),
MIXINS = project.zipTree("/runelite-mixins/build/libs/mixins-1.5.37-SNAPSHOT.jar");
@Test
public void test() throws Exception
{
InjectTaskHandler inj = new Injection(VAN, DEOB, API, MIXINS);
inj.inject();
}
}