diff --git a/src/main/java/nl/sander/beejava/ConstantPoolCreator.java b/src/main/java/nl/sander/beejava/ConstantPoolCreator.java index d1b417f..366c13a 100644 --- a/src/main/java/nl/sander/beejava/ConstantPoolCreator.java +++ b/src/main/java/nl/sander/beejava/ConstantPoolCreator.java @@ -13,6 +13,10 @@ public class ConstantPoolCreator { private int index; // the current index that will be assigned to a constant pool entry. It needs to be unique for each entry. // References to other elements in the pool are made through indexes, so they have to be valid to guarantee that the class can be loaded by the JVM. + public static ConstantPool create(Set constantTree){ + return new ConstantPoolCreator().createConstantPool(constantTree); + } + public ConstantPool createConstantPool(Set constantTree) { constantPool = new ConstantPool(); index = 0; diff --git a/src/main/java/nl/sander/beejava/TypeMapper.java b/src/main/java/nl/sander/beejava/TypeMapper.java index b311038..d12199f 100644 --- a/src/main/java/nl/sander/beejava/TypeMapper.java +++ b/src/main/java/nl/sander/beejava/TypeMapper.java @@ -17,11 +17,19 @@ public class TypeMapper { MAP.put(short.class, "S"); MAP.put(boolean.class, "Z"); } -//TODO something with arrays + + //TODO something with arrays public static String map(Class type) { - return Optional.ofNullable(MAP.get(type)) - .orElseThrow(() -> new RuntimeException("Type " + type.getName() + " not found")); + return Optional.ofNullable(MAP.get(type)).orElseGet(() -> { + if (type.isArray()) { + return internalName(type.getName()); + } else { + return "L" + internalName(type.getName()); + } + }); } - + private static String internalName(String name) { + return name.replaceAll("\\.", "/"); + } } diff --git a/src/main/java/nl/sander/beejava/constantpool/entry/ClassEntry.java b/src/main/java/nl/sander/beejava/constantpool/entry/ClassEntry.java index 6aacf2b..dcf8264 100644 --- a/src/main/java/nl/sander/beejava/constantpool/entry/ClassEntry.java +++ b/src/main/java/nl/sander/beejava/constantpool/entry/ClassEntry.java @@ -17,7 +17,7 @@ public class ClassEntry extends ConstantPoolEntry { @Override public String toString() { - return "Class\t\t#" + getNameIndex() + "\t\t// " + name.getUtf8(); + return "Class\t\t\t#" + getNameIndex() + "\t\t// " + name.getUtf8(); } @Override diff --git a/src/main/java/nl/sander/beejava/constantpool/entry/FieldRefEntry.java b/src/main/java/nl/sander/beejava/constantpool/entry/FieldRefEntry.java index eb1f4c9..3c79854 100644 --- a/src/main/java/nl/sander/beejava/constantpool/entry/FieldRefEntry.java +++ b/src/main/java/nl/sander/beejava/constantpool/entry/FieldRefEntry.java @@ -24,8 +24,8 @@ public class FieldRefEntry extends ConstantPoolEntry { @Override public String toString() { - return "FieldRef\t#" + getClassIndex() + - ".#=" + getNameAndTypeIndex() +"\t// "+classEntry.getName()+'.'+nameAndTypeEntry.toString(); + return "FieldRef\t\t#" + getClassIndex() + + ".#=" + getNameAndTypeIndex() + "\t// " + classEntry.getName() + '.' + nameAndTypeEntry.getName() + ':' + nameAndTypeEntry.getType(); } diff --git a/src/test/java/nl/sander/beejava/CompilerTests.java b/src/test/java/nl/sander/beejava/CompilerTests.java index cf4f4eb..f3e6b85 100644 --- a/src/test/java/nl/sander/beejava/CompilerTests.java +++ b/src/test/java/nl/sander/beejava/CompilerTests.java @@ -15,8 +15,13 @@ public class CompilerTests { // creates simplest class possible and checks the tree, that the ConstantTreeCreator emits @Test // This is not a maintainable test public void testMethodRefEntryForSuperConstructor() { + // Arrange BeeClass classWithIntField = TestData.emptyClass(); + + // Act CompiledClass compiledClass = Compiler.compile(classWithIntField); + + // Assert Set constantTree = compiledClass.getConstantTree(); assertEquals(2, constantTree.size()); ConstantPoolEntry superConstructor = constantTree.iterator().next(); diff --git a/src/test/java/nl/sander/beejava/ConstantPoolUniquenessTests.java b/src/test/java/nl/sander/beejava/ConstantPoolUniquenessTests.java index 6b71407..b0cc285 100644 --- a/src/test/java/nl/sander/beejava/ConstantPoolUniquenessTests.java +++ b/src/test/java/nl/sander/beejava/ConstantPoolUniquenessTests.java @@ -1,13 +1,32 @@ package nl.sander.beejava; import nl.sander.beejava.api.BeeClass; +import nl.sander.beejava.constantpool.ConstantPool; +import nl.sander.beejava.constantpool.entry.ClassEntry; import org.junit.jupiter.api.Test; +import java.util.List; +import java.util.stream.Collectors; + +import static org.junit.jupiter.api.Assertions.assertEquals; + public class ConstantPoolUniquenessTests { @Test - public void test(){ + public void test() { + // Arrange BeeClass someClass = TestData.createClassWithTwoReferencesToSomeClass(); + + // Act CompiledClass compiledClass = Compiler.compile(someClass); - BytecodeGenerator.generate(compiledClass); + ConstantPool constantPool = new ConstantPoolCreator().createConstantPool(compiledClass.getConstantTree()); + + // Assert + List refsToSystem = constantPool.stream() + .filter(cpe -> cpe instanceof ClassEntry) + .map(cpe -> (ClassEntry) cpe) + .filter(ce -> ce.getName().equals("java/lang/System")) + .collect(Collectors.toList()); + + assertEquals(1, refsToSystem.size()); } } diff --git a/src/test/java/nl/sander/beejava/TestData.java b/src/test/java/nl/sander/beejava/TestData.java index 3bc1efb..6b51390 100644 --- a/src/test/java/nl/sander/beejava/TestData.java +++ b/src/test/java/nl/sander/beejava/TestData.java @@ -44,34 +44,43 @@ public class TestData { line(3, RETURN)) .build(); + BeeMethod print2 = BeeMethod.builder() + .withAccessFlags(MethodAccessFlag.PUBLIC) + .withCode( + line(0, GET, "java.lang.System","out"), + line(1, LD_CONST, "2"), + line(2, INVOKE, "java.io.PrintStream", "println", "(java.lang.String)"), + line(3, RETURN)) + .build(); + return BeeClass.builder() .withClassFileVersion(Version.V14) .withPackage("nl.sander.beejava.test") .withAccessFlags(PUBLIC) .withSimpleName("ClassWithReferences") .withConstructors(createConstructor()) // There's no default constructor in beejava. The user must always add them - .withMethods(print1) + .withMethods(print1, print2) .build(); } - public static BeeClass createClassWithIntField() { - BeeField intField = BeeField.builder() + public static BeeClass createClassWithField(Class fieldType) { + BeeField field = BeeField.builder() .withAccessFlags(FieldAccessFlag.PRIVATE) - .withType(int.class) - .withName("intField") + .withType(fieldType) + .withName("field") .build(); - BeeParameter intValueParameter = BeeParameter.create(int.class, "intValue"); + BeeParameter parameter = BeeParameter.create(fieldType, "value"); BeeConstructor constructor = BeeConstructor.builder() .withAccessFlags(MethodAccessFlag.PUBLIC) - .withFormalParameters(intValueParameter) + .withFormalParameters(parameter) .withCode( line(0, LD_VAR, Ref.THIS), line(1, INVOKE, Ref.SUPER, "", "()"), line(2, LD_VAR, Ref.THIS), - line(3, LD_VAR, intValueParameter), - line(4, PUT, intField), + line(3, LD_VAR, parameter), + line(4, PUT, field), line(5, RETURN)) .build(); @@ -79,9 +88,9 @@ public class TestData { .withClassFileVersion(Version.V14) .withPackage("nl.sander.beejava.test") .withAccessFlags(PUBLIC) - .withSimpleName("IntBean") + .withSimpleName("Bean") .withSuperClass(Object.class) - .withFields(intField) + .withFields(field) .withConstructors(constructor) .build(); } diff --git a/src/test/java/nl/sander/beejava/TypeMapperTest.java b/src/test/java/nl/sander/beejava/TypeMapperTest.java new file mode 100644 index 0000000..8468404 --- /dev/null +++ b/src/test/java/nl/sander/beejava/TypeMapperTest.java @@ -0,0 +1,168 @@ +package nl.sander.beejava; + +import nl.sander.beejava.api.BeeClass; +import nl.sander.beejava.constantpool.ConstantPool; +import nl.sander.beejava.constantpool.entry.NameAndTypeEntry; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +public class TypeMapperTest { + + @Test + public void test_int() { + // Arrange + BeeClass beeClass = TestData.createClassWithField(int.class); + + // Act + ConstantPool constantPool = createConstantPool(beeClass); + + // Assert + NameAndTypeEntry fieldEntry = getFieldNameAndType(constantPool); + assertEquals("I", fieldEntry.getType()); + } + + @Test + public void test_double() { + // Arrange + BeeClass beeClass = TestData.createClassWithField(double.class); + + // Act + ConstantPool constantPool = createConstantPool(beeClass); + + // Assert + NameAndTypeEntry fieldEntry = getFieldNameAndType(constantPool); + assertEquals("D", fieldEntry.getType()); + } + + @Test + public void test_float() { + // Arrange + BeeClass beeClass = TestData.createClassWithField(float.class); + + // Act + ConstantPool constantPool = createConstantPool(beeClass); + + // Assert + NameAndTypeEntry fieldEntry = getFieldNameAndType(constantPool); + assertEquals("F", fieldEntry.getType()); + } + + @Test + public void test_byte() { + // Arrange + BeeClass beeClass = TestData.createClassWithField(byte.class); + + // Act + ConstantPool constantPool = createConstantPool(beeClass); + + // Assert + NameAndTypeEntry fieldEntry = getFieldNameAndType(constantPool); + assertEquals("B", fieldEntry.getType()); + } + + @Test + public void test_short() { + // Arrange + BeeClass beeClass = TestData.createClassWithField(short.class); + + // Act + ConstantPool constantPool = createConstantPool(beeClass); + + // Assert + NameAndTypeEntry fieldEntry = getFieldNameAndType(constantPool); + assertEquals("S", fieldEntry.getType()); + } + + @Test + public void test_long() { + // Arrange + BeeClass beeClass = TestData.createClassWithField(long.class); + + // Act + ConstantPool constantPool = createConstantPool(beeClass); + + // Assert + NameAndTypeEntry fieldEntry = getFieldNameAndType(constantPool); + assertEquals("J", fieldEntry.getType()); + } + + @Test + public void test_char() { + // Arrange + BeeClass beeClass = TestData.createClassWithField(char.class); + + // Act + ConstantPool constantPool = createConstantPool(beeClass); + + // Assert + NameAndTypeEntry fieldEntry = getFieldNameAndType(constantPool); + assertEquals("C", fieldEntry.getType()); + } + + @Test + public void test_boolean() { + // Arrange + BeeClass beeClass = TestData.createClassWithField(boolean.class); + + // Act + ConstantPool constantPool = createConstantPool(beeClass); + + // Assert + NameAndTypeEntry fieldEntry = getFieldNameAndType(constantPool); + assertEquals("Z", fieldEntry.getType()); + } + + @Test + public void test_Object() { + // Arrange + BeeClass beeClass = TestData.createClassWithField(Object.class); + + // Act + ConstantPool constantPool = createConstantPool(beeClass); + + // Assert + NameAndTypeEntry fieldEntry = getFieldNameAndType(constantPool); + assertEquals("Ljava/lang/Object", fieldEntry.getType()); + } + + @Test + public void test_int_array() { + // Arrange + BeeClass beeClass = TestData.createClassWithField(int[].class); + + // Act + ConstantPool constantPool = createConstantPool(beeClass); + + // Assert + NameAndTypeEntry fieldEntry = getFieldNameAndType(constantPool); + assertEquals("[I", fieldEntry.getType()); + } + + @Test + public void test_Object_array() { + // Arrange + BeeClass beeClass = TestData.createClassWithField(String[].class); + + // Act + ConstantPool constantPool = createConstantPool(beeClass); + + // Assert + NameAndTypeEntry fieldEntry = getFieldNameAndType(constantPool); + assertEquals("[Ljava/lang/String;", fieldEntry.getType()); + } + + private ConstantPool createConstantPool(BeeClass beeClass) { + CompiledClass compiledClass = Compiler.compile(beeClass); + return ConstantPoolCreator.create(compiledClass.getConstantTree()); + } + + private NameAndTypeEntry getFieldNameAndType(ConstantPool constantPool) { + return constantPool.stream() + .filter(cpe -> cpe instanceof NameAndTypeEntry) + .map(NameAndTypeEntry.class::cast) + .filter(nate -> nate.getName().equals("field")) + .findAny().orElseGet(() -> fail("'field' not found")); + } +} diff --git a/src/test/java/nl/sander/beejava/constantpool/entry/ClassEntryTest.java b/src/test/java/nl/sander/beejava/constantpool/entry/ClassEntryTest.java index f1fb45f..586822a 100644 --- a/src/test/java/nl/sander/beejava/constantpool/entry/ClassEntryTest.java +++ b/src/test/java/nl/sander/beejava/constantpool/entry/ClassEntryTest.java @@ -6,7 +6,7 @@ import static org.junit.jupiter.api.Assertions.assertSame; public class ClassEntryTest { @Test - public void testGetChildren() { + public void test_GetChildren() { Utf8Entry name = new Utf8Entry(""); assertSame(new ClassEntry(name).getChildren().iterator().next(), name); } diff --git a/src/test/java/nl/sander/beejava/constantpool/entry/ConstantPoolEntryTest.java b/src/test/java/nl/sander/beejava/constantpool/entry/ConstantPoolEntryTest.java index c99d26d..997d52d 100644 --- a/src/test/java/nl/sander/beejava/constantpool/entry/ConstantPoolEntryTest.java +++ b/src/test/java/nl/sander/beejava/constantpool/entry/ConstantPoolEntryTest.java @@ -14,19 +14,19 @@ public class ConstantPoolEntryTest { }; @Test - public void getSetIndex() { + public void test_getSetIndex() { int value = 2; entry.setIndex(value); assertEquals(value, entry.getIndex()); } @Test - public void lowerByte() { + public void test_lowerByte() { assertEquals(1, entry.lowerByte(257)); } @Test - public void upperByte() { + public void test_upperByte() { assertEquals(1, entry.upperByte(257)); } } \ No newline at end of file diff --git a/src/test/java/nl/sander/beejava/constantpool/entry/DoubleEntryTest.java b/src/test/java/nl/sander/beejava/constantpool/entry/DoubleEntryTest.java index 1ff3c20..ee8447a 100644 --- a/src/test/java/nl/sander/beejava/constantpool/entry/DoubleEntryTest.java +++ b/src/test/java/nl/sander/beejava/constantpool/entry/DoubleEntryTest.java @@ -4,10 +4,10 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertArrayEquals; -class DoubleEntryTest { +public class DoubleEntryTest { @Test - void getBytes() { + public void test_getBytes() { assertArrayEquals(new byte[]{6, 64, 40, 0, 0, 0, 0, 0, 0}, new DoubleEntry(12D).getBytes()); } } \ No newline at end of file diff --git a/src/test/java/nl/sander/beejava/constantpool/entry/FloatEntryTest.java b/src/test/java/nl/sander/beejava/constantpool/entry/FloatEntryTest.java index 9b7fa9e..4cf5f37 100644 --- a/src/test/java/nl/sander/beejava/constantpool/entry/FloatEntryTest.java +++ b/src/test/java/nl/sander/beejava/constantpool/entry/FloatEntryTest.java @@ -4,10 +4,10 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertArrayEquals; -class FloatEntryTest { +public class FloatEntryTest { @Test - void getBytes() { + public void test_getBytes() { assertArrayEquals(new byte[]{4, 0, 0, 0, 0}, new FloatEntry(0F).getBytes()); } } \ No newline at end of file diff --git a/src/test/java/nl/sander/beejava/constantpool/entry/IntegerEntryTest.java b/src/test/java/nl/sander/beejava/constantpool/entry/IntegerEntryTest.java index f65f8b2..acb67aa 100644 --- a/src/test/java/nl/sander/beejava/constantpool/entry/IntegerEntryTest.java +++ b/src/test/java/nl/sander/beejava/constantpool/entry/IntegerEntryTest.java @@ -4,10 +4,10 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertArrayEquals; -class IntegerEntryTest { +public class IntegerEntryTest { @Test - void getBytes() { + public void test_getBytes() { assertArrayEquals(new byte[]{3, 18, 52, 86, 120}, new IntegerEntry(0x12345678).getBytes()); } } \ No newline at end of file diff --git a/src/test/java/nl/sander/beejava/constantpool/entry/LongEntryTest.java b/src/test/java/nl/sander/beejava/constantpool/entry/LongEntryTest.java index 376fb61..4053f99 100644 --- a/src/test/java/nl/sander/beejava/constantpool/entry/LongEntryTest.java +++ b/src/test/java/nl/sander/beejava/constantpool/entry/LongEntryTest.java @@ -4,10 +4,10 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertArrayEquals; -class LongEntryTest { +public class LongEntryTest { @Test - void getBytes() { + public void test_getBytes() { assertArrayEquals(new byte[]{5, 18, 52, 86, 120, -102, -68, -34, -16}, new LongEntry(0x123456789ABCDEF0L).getBytes()); } } \ No newline at end of file diff --git a/src/test/java/nl/sander/beejava/flags/ClassAccessFlagTest.java b/src/test/java/nl/sander/beejava/flags/ClassAccessFlagTest.java index 6a691c6..7f868f6 100644 --- a/src/test/java/nl/sander/beejava/flags/ClassAccessFlagTest.java +++ b/src/test/java/nl/sander/beejava/flags/ClassAccessFlagTest.java @@ -1,6 +1,5 @@ package nl.sander.beejava.flags; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.util.Arrays; @@ -10,12 +9,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals; public class ClassAccessFlagTest { @Test - public void mustOr1Value() { + public void test_mustOr1Value() { assertEquals(1, ClassAccessFlag.getSum(Collections.singletonList(ClassAccessFlag.PUBLIC))); } @Test - public void mustOr2Values() { + public void test_mustOr2Values() { assertEquals(17, ClassAccessFlag.getSum(Arrays.asList(ClassAccessFlag.PUBLIC, ClassAccessFlag.FINAL))); }