Improve rendering of failures in AbstractWriteFlagsTest

When expected and actual flag values are not equal, transform them to
presentable strings according to `Opcodes.ACC_*` field values.
This commit is contained in:
Alexander Udalov
2020-11-06 18:05:58 +01:00
committed by Alexander Udalov
parent 0e91d3fcb0
commit 9d3c9a823d
@@ -21,12 +21,13 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.output.OutputFile; import org.jetbrains.kotlin.backend.common.output.OutputFile;
import org.jetbrains.kotlin.codegen.CodegenTestCase; import org.jetbrains.kotlin.codegen.CodegenTestCase;
import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
import org.jetbrains.org.objectweb.asm.*; import org.jetbrains.org.objectweb.asm.*;
import java.io.File; import java.io.File;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList; import java.lang.reflect.Modifier;
import java.util.List; import java.util.*;
import static org.jetbrains.kotlin.test.InTextDirectivesUtils.findListWithPrefixes; import static org.jetbrains.kotlin.test.InTextDirectivesUtils.findListWithPrefixes;
import static org.jetbrains.kotlin.test.InTextDirectivesUtils.findStringWithPrefixes; import static org.jetbrains.kotlin.test.InTextDirectivesUtils.findStringWithPrefixes;
@@ -91,8 +92,14 @@ public abstract class AbstractWriteFlagsTest extends CodegenTestCase {
assertEquals("Wrong object existence state: " + testedObject, isObjectExists, classVisitor.isExists()); assertEquals("Wrong object existence state: " + testedObject, isObjectExists, classVisitor.isExists());
if (isObjectExists) { if (isObjectExists) {
assertEquals("Wrong access flag for " + testedObject + " \n" + outputFile.asText(), int expected = getExpectedFlags(testedObject.textData);
getExpectedFlags(testedObject.textData), classVisitor.getAccess()); int actual = classVisitor.getAccess();
if (expected != actual) {
assertEquals(
"Wrong access flag for " + testedObject + " \n" + outputFile.asText(),
flagsToText(expected), flagsToText(actual)
);
}
} }
} }
} }
@@ -180,14 +187,25 @@ public abstract class AbstractWriteFlagsTest extends CodegenTestCase {
} }
} }
private static String flagsToText(int flags) {
StringBuilder sb = new StringBuilder();
sb.append(flags).append(" = ").append(String.format("0x%04x", flags)).append("\n");
for (int flag = 1; flag > 0; flag <<= 1) {
if ((flags & flag) != 0) {
String string = FLAG_TO_STRING.get(flag);
sb.append(string == null ? "unknown (" + flag + ")" : string).append("\n");
}
}
return sb.toString();
}
private static int getExpectedFlags(String text) { private static int getExpectedFlags(String text) {
int expectedAccess = 0; int expectedAccess = 0;
Class<?> klass = Opcodes.class;
List<String> flags = findListWithPrefixes(text, "// FLAGS: "); List<String> flags = findListWithPrefixes(text, "// FLAGS: ");
for (String flag : flags) { for (String flag : flags) {
try { try {
Field field = klass.getDeclaredField(flag); Field field = Opcodes.class.getDeclaredField(flag);
expectedAccess |= field.getInt(klass); expectedAccess |= field.getInt(null);
} }
catch (NoSuchFieldException | IllegalAccessException e) { catch (NoSuchFieldException | IllegalAccessException e) {
throw new IllegalArgumentException("Cannot find " + flag + " field in Opcodes class", e); throw new IllegalArgumentException("Cannot find " + flag + " field in Opcodes class", e);
@@ -196,6 +214,25 @@ public abstract class AbstractWriteFlagsTest extends CodegenTestCase {
return expectedAccess; return expectedAccess;
} }
private static final Map<Integer, String> FLAG_TO_STRING;
static {
Map<Integer, String> flagToString = new HashMap<>();
try {
for (Field field : Opcodes.class.getDeclaredFields()) {
String name = field.getName();
if (Modifier.isStatic(field.getModifiers()) && name.startsWith("ACC_")) {
int value = field.getInt(null);
String previous = flagToString.get(value);
flagToString.put(value, previous == null ? name : previous + "/" + name);
}
}
} catch (IllegalAccessException e) {
throw ExceptionUtilsKt.rethrow(e);
}
FLAG_TO_STRING = Collections.unmodifiableMap(flagToString);
}
private static class ClassFlagsVisitor extends TestClassVisitor { private static class ClassFlagsVisitor extends TestClassVisitor {
private int access = 0; private int access = 0;