Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions vm/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
</modules>

<properties>
<maven.compiler.source>1.5</maven.compiler.source>
<maven.compiler.target>1.5</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<asm.version>5.0.3</asm.version>
<junit.jupiter.version>5.10.2</junit.jupiter.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import com.codename1.tools.translator.bytecodes.MultiArray;
import com.codename1.tools.translator.bytecodes.VarOp;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
Expand Down Expand Up @@ -39,8 +41,12 @@

class BytecodeInstructionIntegrationTest {

@Test
void translatesOptimizedBytecodeToLLVMExecutable() throws Exception {
@ParameterizedTest
@ValueSource(strings = {"1.5", "1.8"})
void translatesOptimizedBytecodeToLLVMExecutable(String targetVersion) throws Exception {
if ("1.5".equals(targetVersion) && !isSourceVersionSupported("1.5")) {
return; // Skip on newer JDKs that dropped 1.5 support
}
Parser.cleanup();

Path sourceDir = Files.createTempDirectory("bytecode-integration-sources");
Expand All @@ -61,9 +67,9 @@ void translatesOptimizedBytecodeToLLVMExecutable() throws Exception {
// Compile App using JavaAPI as bootclasspath
List<String> compileArgs = new ArrayList<>();
compileArgs.add("-source");
compileArgs.add("1.5");
compileArgs.add(targetVersion);
compileArgs.add("-target");
compileArgs.add("1.5");
compileArgs.add(targetVersion);
compileArgs.add("-bootclasspath");
compileArgs.add(javaApiDir.toString());
compileArgs.add("-d");
Expand Down Expand Up @@ -183,8 +189,12 @@ private String invokeLdcLocalVarsAppSource() {
"}\n";
}

@Test
void translatesInvokeAndLdcBytecodeToLLVMExecutable() throws Exception {
@ParameterizedTest
@ValueSource(strings = {"1.5", "1.8"})
void translatesInvokeAndLdcBytecodeToLLVMExecutable(String targetVersion) throws Exception {
if ("1.5".equals(targetVersion) && !isSourceVersionSupported("1.5")) {
return; // Skip on newer JDKs that dropped 1.5 support
}
Parser.cleanup();

Path sourceDir = Files.createTempDirectory("invoke-ldc-sources");
Expand All @@ -204,9 +214,9 @@ void translatesInvokeAndLdcBytecodeToLLVMExecutable() throws Exception {

List<String> compileArgs = new ArrayList<>();
compileArgs.add("-source");
compileArgs.add("1.5");
compileArgs.add(targetVersion);
compileArgs.add("-target");
compileArgs.add("1.5");
compileArgs.add(targetVersion);
compileArgs.add("-bootclasspath");
compileArgs.add(javaApiDir.toString());
compileArgs.add("-d");
Expand Down Expand Up @@ -974,15 +984,19 @@ private String nativeReportSource() {
"}\n";
}

@Test
void handleDefaultOutputWritesOutput() throws Exception {
@ParameterizedTest
@ValueSource(strings = {"1.5", "1.8"})
void handleDefaultOutputWritesOutput(String targetVersion) throws Exception {
if ("1.5".equals(targetVersion) && !isSourceVersionSupported("1.5")) {
return; // Skip on newer JDKs that dropped 1.5 support
}
Parser.cleanup();
resetByteCodeClass();
Path sourceDir = Files.createTempDirectory("default-output-source");
Path outputDir = Files.createTempDirectory("default-output-dest");

Files.write(sourceDir.resolve("resource.txt"), "data".getBytes(StandardCharsets.UTF_8));
compileDummyMainClass(sourceDir, "com.example", "MyAppDefault");
compileDummyMainClass(sourceDir, "com.example", "MyAppDefault", targetVersion);

String[] args = new String[] {
"csharp",
Expand Down Expand Up @@ -1061,15 +1075,19 @@ void copyDirRecursivelyCopies() throws Exception {
assertTrue(Files.exists(copiedRoot.resolve("subdir/file2.txt")));
}

@Test
void handleIosOutputGeneratesProjectStructure() throws Exception {
@ParameterizedTest
@ValueSource(strings = {"1.5", "1.8"})
void handleIosOutputGeneratesProjectStructure(String targetVersion) throws Exception {
if ("1.5".equals(targetVersion) && !isSourceVersionSupported("1.5")) {
return; // Skip on newer JDKs that dropped 1.5 support
}
Parser.cleanup();
resetByteCodeClass();
Path sourceDir = Files.createTempDirectory("ios-output-source");
Path outputDir = Files.createTempDirectory("ios-output-dest");

Files.write(sourceDir.resolve("resource.txt"), "data".getBytes(StandardCharsets.UTF_8));
compileDummyMainClass(sourceDir, "com.example", "MyAppIOS");
compileDummyMainClass(sourceDir, "com.example", "MyAppIOS", targetVersion);

// Add a bundle to test copyDir invocation in execute loop
Path bundleDir = sourceDir.resolve("test.bundle");
Expand Down Expand Up @@ -1121,7 +1139,7 @@ private void resetByteCodeClass() throws Exception {
((Set<?>) writableFieldsField.get(null)).clear();
}

private void compileDummyMainClass(Path sourceDir, String packageName, String className) throws Exception {
private void compileDummyMainClass(Path sourceDir, String packageName, String className, String targetVersion) throws Exception {
Path packageDir = sourceDir;
for (String part : packageName.split("\\.")) {
packageDir = packageDir.resolve(part);
Expand All @@ -1136,8 +1154,8 @@ private void compileDummyMainClass(Path sourceDir, String packageName, String cl

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
int result = compiler.run(null, null, null,
"-source", "1.5",
"-target", "1.5",
"-source", targetVersion,
"-target", targetVersion,
"-d", sourceDir.toString(),
javaFile.toString());
assertEquals(0, result, "Compilation failed");
Expand Down Expand Up @@ -1243,4 +1261,20 @@ void testArithmeticExpressionCoverage() {
// Let's rely on integration tests for complex dependency checks in ArithmeticExpression,
// or mock if possible. But here we can check basic behavior.
}

private boolean isSourceVersionSupported(String version) {
String javaVersion = System.getProperty("java.specification.version");
if (javaVersion.startsWith("1.")) {
return true;
}
try {
int major = Integer.parseInt(javaVersion);
if ("1.5".equals(version)) {
if (major >= 9) return false;
}
} catch (NumberFormatException e) {
return true;
}
return true;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.codename1.tools.translator;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
Expand All @@ -23,8 +25,12 @@

class CleanTargetIntegrationTest {

@Test
void generatesRunnableHelloWorldUsingCleanTarget() throws Exception {
@ParameterizedTest
@ValueSource(strings = {"1.5", "1.8"})
void generatesRunnableHelloWorldUsingCleanTarget(String targetVersion) throws Exception {
if ("1.5".equals(targetVersion) && !isSourceVersionSupported("1.5")) {
return; // Skip on newer JDKs that dropped 1.5 support
}
Parser.cleanup();

Path sourceDir = Files.createTempDirectory("clean-target-sources");
Expand All @@ -47,6 +53,8 @@ void generatesRunnableHelloWorldUsingCleanTarget() throws Exception {
null,
null,
null,
"-source", targetVersion,
"-target", targetVersion,
"-d", classesDir.toString(),
javaFile.toString(),
sourceDir.resolve("java/lang/Object.java").toString(),
Expand Down Expand Up @@ -452,4 +460,20 @@ static String nativeHelloSource() {
" printf(\"Hello, Clean Target!\\n\");\n" +
"}\n";
}

private boolean isSourceVersionSupported(String version) {
String javaVersion = System.getProperty("java.specification.version");
if (javaVersion.startsWith("1.")) {
return true;
}
try {
int major = Integer.parseInt(javaVersion);
if ("1.5".equals(version)) {
if (major >= 9) return false;
}
} catch (NumberFormatException e) {
return true;
}
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import com.codename1.tools.translator.bytecodes.Instruction;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
Expand All @@ -24,9 +26,10 @@ void cleanParser() {
Parser.cleanup();
}

@Test
void parsesBasicClassWithFieldsAndMethodBodies() throws Exception {
Path classFile = createSampleClass();
@ParameterizedTest
@ValueSource(ints = {Opcodes.V1_5, Opcodes.V1_8})
void parsesBasicClassWithFieldsAndMethodBodies(int opcodeVersion) throws Exception {
Path classFile = createSampleClass(opcodeVersion);

Parser.parse(classFile.toFile());

Expand Down Expand Up @@ -54,9 +57,10 @@ void parsesBasicClassWithFieldsAndMethodBodies() throws Exception {
assertEquals(Opcodes.IRETURN, opcodes.get(opcodes.size() - 1));
}

@Test
void parsesInterfacesAsAbstractContracts() throws Exception {
Path classFile = createTaskInterface();
@ParameterizedTest
@ValueSource(ints = {Opcodes.V1_5, Opcodes.V1_8})
void parsesInterfacesAsAbstractContracts(int opcodeVersion) throws Exception {
Path classFile = createTaskInterface(opcodeVersion);

Parser.parse(classFile.toFile());

Expand All @@ -69,9 +73,10 @@ void parsesInterfacesAsAbstractContracts() throws Exception {
assertTrue(method.canBeVirtual());
}

@Test
void parsesEnumMetadataAndBaseType() throws Exception {
Path classFile = createPriorityEnum();
@ParameterizedTest
@ValueSource(ints = {Opcodes.V1_5, Opcodes.V1_8})
void parsesEnumMetadataAndBaseType(int opcodeVersion) throws Exception {
Path classFile = createPriorityEnum(opcodeVersion);

Parser.parse(classFile.toFile());

Expand All @@ -81,9 +86,10 @@ void parsesEnumMetadataAndBaseType() throws Exception {
assertTrue(readPrivateBoolean(cls, "isEnum"));
}

@Test
void parsesAnnotationsWithCorrectFlags() throws Exception {
Path classFile = createAnnotation();
@ParameterizedTest
@ValueSource(ints = {Opcodes.V1_5, Opcodes.V1_8})
void parsesAnnotationsWithCorrectFlags(int opcodeVersion) throws Exception {
Path classFile = createAnnotation(opcodeVersion);

Parser.parse(classFile.toFile());

Expand Down Expand Up @@ -123,9 +129,9 @@ private boolean readPrivateBoolean(Object target, String fieldName) throws Excep
return field.getBoolean(target);
}

private Path createSampleClass() throws Exception {
private Path createSampleClass(int opcodeVersion) throws Exception {
return writeClass("com/example/Sample", cw -> {
cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER, "com/example/Sample", null, "java/lang/Object", null);
cw.visit(opcodeVersion, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER, "com/example/Sample", null, "java/lang/Object", null);
cw.visitField(Opcodes.ACC_PRIVATE, "counter", "I", null, null).visitEnd();
cw.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL, "GREETING", "Ljava/lang/String;", null, "hi").visitEnd();
cw.visitField(Opcodes.ACC_PUBLIC, "names", "Ljava/util/List;", "Ljava/util/List<Ljava/lang/String;>;", null).visitEnd();
Expand All @@ -151,10 +157,10 @@ private Path createSampleClass() throws Exception {
});
}

private Path createTaskInterface() throws Exception {
private Path createTaskInterface(int opcodeVersion) throws Exception {
return writeClass("com/example/Task", cw -> {
cw.visit(
Opcodes.V1_5,
opcodeVersion,
Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE,
"com/example/Task",
null,
Expand All @@ -166,10 +172,10 @@ private Path createTaskInterface() throws Exception {
});
}

private Path createPriorityEnum() throws Exception {
private Path createPriorityEnum(int opcodeVersion) throws Exception {
return writeClass("com/example/Priority", cw -> {
cw.visit(
Opcodes.V1_5,
opcodeVersion,
Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_SUPER | Opcodes.ACC_ENUM,
"com/example/Priority",
null,
Expand Down Expand Up @@ -252,10 +258,10 @@ private Path createPriorityEnum() throws Exception {
});
}

private Path createAnnotation() throws Exception {
private Path createAnnotation(int opcodeVersion) throws Exception {
return writeClass("com/example/TestAnnotation", cw -> {
cw.visit(
Opcodes.V1_5,
opcodeVersion,
Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE | Opcodes.ACC_ANNOTATION,
"com/example/TestAnnotation",
null,
Expand Down
Loading