Commit 162b4cfe authored by Stephanie Gawroriski's avatar Stephanie Gawroriski
Browse files

Merge in third cherry picking.

parents 37688f5c eb231029
Pipeline #39199 passed with stages
in 1 minute and 36 seconds
......@@ -57,6 +57,8 @@
<module name="squirreljme.modules.springcoat-vm.main" target="1.7" />
<module name="squirreljme.modules.springcoat-vm.test" target="1.7" />
<module name="squirreljme.modules.squirrel-quarrel.testFixtures" target="1.7" />
<module name="squirreljme.modules.strings.main" target="1.7" />
<module name="squirreljme.modules.strings.test" target="1.7" />
<module name="squirreljme.modules.strings.testFixtures" target="1.7" />
<module name="squirreljme.modules.summercoat-vm.main" target="1.7" />
<module name="squirreljme.modules.summercoat-vm.test" target="1.7" />
......@@ -103,4 +105,4 @@
<module name="squirreljme.utilities.test" target="1.7" />
</bytecodeTargetLevel>
</component>
</project>
\ No newline at end of file
</project>
......@@ -30,6 +30,11 @@ idea
// These are auto-generated by Fossil and should be ignored
excludeDirs += file("manifest")
excludeDirs += file("manifest.uuid")
// IntelliJ's own dependency matrix output (in "out")
project.allprojects.each() { Project subProj ->
excludeDirs += subProj.projectDir.toPath().resolve("out").toFile()
}
}
}
......
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
// Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
......
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
// Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
......
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
// Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
......
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
// Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
......
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// Multi-Phasic Applications: SquirrelJME
// Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
......
......@@ -17,17 +17,31 @@ package cc.squirreljme.plugin.multivm;
public enum VMTestResult
{
/** Pass. */
PASS,
PASS(0),
/** Fail. */
FAIL,
FAIL(1),
/** Skip. */
SKIP,
SKIP(2),
/* End. */
;
/** The mapped exit code. */
public final int exitCode;
/**
* Initializes the result with the exit code.
*
* @param __exitCode The exit code.
* @since 2021/07/18
*/
VMTestResult(int __exitCode)
{
this.exitCode = __exitCode;
}
/**
* Decodes the exit value and returns the test result.
*
......@@ -37,9 +51,9 @@ public enum VMTestResult
*/
public static VMTestResult valueOf(int __exitValue)
{
if (__exitValue == 0)
if (__exitValue == VMTestResult.PASS.exitCode)
return VMTestResult.PASS;
else if (__exitValue == 2)
else if (__exitValue == VMTestResult.SKIP.exitCode)
return VMTestResult.SKIP;
return VMTestResult.FAIL;
}
......
......@@ -33,6 +33,10 @@ public abstract class VMTestWorkAction
private static final long _TEST_TIMEOUT =
360_000_000_000L;
/** Skip sequence special. */
private static final byte[] _SKIP_SPECIAL =
new byte[]{'%', '!', 'S', 'k', 'O', 'n', 'T', 'i', '!', '%'};
/**
* {@inheritDoc}
* @since 2020/09/07
......@@ -92,23 +96,28 @@ public abstract class VMTestWorkAction
// Wait for the process to terminate, the exit code will contain
// the result of the test (pass, skip, fail)
int exitCode = -1;
boolean timeOutHit = false;
for (;;)
try
{
// Has the test run expired? Only when not debugging
if (!isDebugging)
{
long nsDur = System.nanoTime() - nsStart;
if (nsDur >= VMTestWorkAction._TEST_TIMEOUT)
{
// Note it
System.err.printf("TIME %s (%d/%d)%n", testName,
count, total);
System.err.flush();
// The logic for interrupts is the same
throw new InterruptedException("Test Timeout");
}
long nsDur = System.nanoTime() - nsStart;
if (nsDur >= VMTestWorkAction._TEST_TIMEOUT)
{
// Note it
System.err.printf("TIME %s (%d/%d)%n", testName,
count, total);
System.err.flush();
// Set timeout as being hit, used for special
// check
timeOutHit = true;
// The logic for interrupts is the same
throw new InterruptedException("Test Timeout");
}
}
// Wait for completion
......@@ -136,6 +145,10 @@ public abstract class VMTestWorkAction
// Clock the ending time
long nsDur = System.nanoTime() - nsStart;
byte[] stdErrBytes = stdErr.getBytes(stdErrThread);
if (timeOutHit && VMTestWorkAction.__findTimeoutSkip(stdErrBytes))
exitCode = VMTestResult.SKIP.exitCode;
// Note this has finished
VMTestResult testResult = VMTestResult.valueOf(exitCode);
System.err.printf("%4s %s (%d/%d)%n", testResult, testName,
......@@ -154,7 +167,7 @@ public abstract class VMTestWorkAction
VMTestWorkAction.__writeXml(out, testName, testResult,
parameters.getVmName().get(), clockStart, nsDur,
stdOut.getBytes(stdOutThread),
stdErr.getBytes(stdErrThread));
stdErrBytes);
// Make sure everything is written
out.flush();
......@@ -185,6 +198,47 @@ public abstract class VMTestWorkAction
}
}
/**
* Finds the special timeout sequence if this has had a timeout, this is
* used to detect if a test should just skip rather than causing a fail.
*
* @param __stdErrBytes The standard error bytes.
* @return If the sequence was found.
* @throws NullPointerException On null arguments.
* @since 2021/07/18
*/
private static boolean __findTimeoutSkip(byte[] __stdErrBytes)
throws NullPointerException
{
if (__stdErrBytes == null)
throw new NullPointerException("NARG");
// Skip special sequence
byte[] skipSpecial = VMTestWorkAction._SKIP_SPECIAL;
byte firstByte = skipSpecial[0];
int skipLen = skipSpecial.length;
// Find the sequence
for (int i = 0, n = Math.max(0, __stdErrBytes.length - skipLen);
i < n; i++)
{
// If the first byte is a match, then
byte quick = __stdErrBytes[i];
if (quick != firstByte)
continue;
// Check if the entire sequence matched
for (int j = 0, q = i; j <= skipLen; j++, q++)
if (j == skipLen)
return true;
else if (__stdErrBytes[q] != skipSpecial[j])
break;
}
// Not found
return false;
}
/**
* Writes the XML test result to the given output.
*
......
......@@ -197,6 +197,12 @@ The following _System_ properties are available:
* If only `:port` is specified it will listen for incoming connections from
a debugger.
* If both `hostname:port` is specified it will connect to a remote debugger.
* Note that if the hosted environment is debugged, launched sub-tasks will
not be run under the debugger.
* `squirreljme.xjdwp=[hostname]:port` -- Enable JDWP for Hosted environment.
* Does the same as `squirreljme.jdwp` but takes priority if both are
specified in the event that debugging should be done for the hosted
process.
* `squirreljme.midlet=value` -- The MIDlet to run, in the following order:
* If `value` is a number and is `-1`, then no MIDlet will be selected and
the `Main-Class` attribute will be force selected.
......@@ -212,6 +218,9 @@ The following _System_ properties are available:
* As an example `squirreljme.sysprop.favorite.animal=squirrel`:
* Will define system property `favorite.animal=squirrel` within the
virtual machine.
* `squirreljme.thread=value` -- The threading model to use.
* `single` or `coop` -- Single Cooperatively Threaded.
* `multi` or `smt` -- Simultaneous Multi-Threading.
* `test.single=classname` -- Run only the given test:
* Will be the test class to be run.
* Multi-parameter tests are in the form of `classname@parameter`, if a
......
......@@ -24,13 +24,6 @@ compileJava
// try to use them during compilation.
dependencies
{
// SquirrelJME just uses TestNG here since it is flexible enough to
// support how SquirrelJME needs to be (testing more as if it were running
// on the target device). Due to the flexibility it allows easier switching
// from Java SE, SpringCoat, and SummerCoat
compileClasspath "org.testng:testng:7.1.0"
runtimeClasspath "org.testng:testng:7.1.0"
// We need these two modules to obtain the SquirrelJME specific classes
compileClasspath project(":modules:cldc-compact")
compileClasspath project(":modules:common-vm")
......
......@@ -3,11 +3,9 @@
dependencies
{
// Need TestNG to run our tests
testImplementation "org.testng:testng:7.1.0"
// Needed to access all of the testing framework details
testImplementation project(":modules:cldc-compact")
testImplementation project(":modules:common-vm")
testImplementation project(":modules:tac")
testImplementation project(":modules:meep-midlet")
testImplementation project(":emulators:emulator-base")
......
......@@ -12,10 +12,18 @@
// The class to forward to
#define JARSHELF_CLASSNAME "cc/squirreljme/emulator/EmulatedJarPackageShelf"
#define JARSHELF_CLASSPATH_DESC "()[Lcc/squirreljme/jvm/mle/brackets/JarPackageBracket;"
#define JARSHELF_LIBRARIES_DESC "()[Lcc/squirreljme/jvm/mle/brackets/JarPackageBracket;"
#define JARSHELF_LIBRARYPATH_DESC "(Lcc/squirreljme/jvm/mle/brackets/JarPackageBracket;)Ljava/lang/String;"
#define JARSHELF_OPENRESOURCE_DESC "(Lcc/squirreljme/jvm/mle/brackets/JarPackageBracket;Ljava/lang/String;)Ljava/io/InputStream;"
JNIEXPORT jobject JNICALL Impl_mle_JarShelf_classPath(JNIEnv* env,
jclass classy)
{
return forwardCallStaticObject(env, JARSHELF_CLASSNAME,
"classPath", JARSHELF_CLASSPATH_DESC);
}
JNIEXPORT jobject JNICALL Impl_mle_JarShelf_libraries(JNIEnv* env,
jclass classy)
{
......@@ -41,6 +49,7 @@ JNIEXPORT jobject JNICALL Impl_mle_JarShelf_openResource(JNIEnv* env,
static const JNINativeMethod mleJarMethods[] =
{
{"classPath", JARSHELF_CLASSPATH_DESC, (void*)Impl_mle_JarShelf_classPath},
{"libraries", JARSHELF_LIBRARIES_DESC, (void*)Impl_mle_JarShelf_libraries},
{"libraryPath", JARSHELF_LIBRARYPATH_DESC, (void*)Impl_mle_JarShelf_libraryPath},
{"openResource", JARSHELF_OPENRESOURCE_DESC, (void*)Impl_mle_JarShelf_openResource},
......
......@@ -73,134 +73,6 @@ JNIEXPORT void JNICALL Java_cc_squirreljme_jvm_Assembly_atomicIncrement
JNIEXPORT void JNICALL Java_cc_squirreljme_jvm_Assembly_breakpoint
(JNIEnv* env, jclass classy);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: classInfoOfBoolean
* Signature: ()Lcc/squirreljme/jvm/ClassInfo;
*/
JNIEXPORT jobject JNICALL Java_cc_squirreljme_jvm_Assembly_classInfoOfBoolean
(JNIEnv* env, jclass classy);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: classInfoOfBooleanPointer
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_cc_squirreljme_jvm_Assembly_classInfoOfBooleanPointer
(JNIEnv* env, jclass classy);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: classInfoOfByte
* Signature: ()Lcc/squirreljme/jvm/ClassInfo;
*/
JNIEXPORT jobject JNICALL Java_cc_squirreljme_jvm_Assembly_classInfoOfByte
(JNIEnv* env, jclass classy);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: classInfoOfBytePointer
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_cc_squirreljme_jvm_Assembly_classInfoOfBytePointer
(JNIEnv* env, jclass classy);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: classInfoOfCharacter
* Signature: ()Lcc/squirreljme/jvm/ClassInfo;
*/
JNIEXPORT jobject JNICALL Java_cc_squirreljme_jvm_Assembly_classInfoOfCharacter
(JNIEnv* env, jclass classy);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: classInfoOfCharacterPointer
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_cc_squirreljme_jvm_Assembly_classInfoOfCharacterPointer
(JNIEnv* env, jclass classy);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: classInfoOfDouble
* Signature: ()Lcc/squirreljme/jvm/ClassInfo;
*/
JNIEXPORT jobject JNICALL Java_cc_squirreljme_jvm_Assembly_classInfoOfDouble
(JNIEnv* env, jclass classy);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: classInfoOfDoublePointer
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_cc_squirreljme_jvm_Assembly_classInfoOfDoublePointer
(JNIEnv* env, jclass classy);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: classInfoOfFloat
* Signature: ()Lcc/squirreljme/jvm/ClassInfo;
*/
JNIEXPORT jobject JNICALL Java_cc_squirreljme_jvm_Assembly_classInfoOfFloat
(JNIEnv* env, jclass classy);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: classInfoOfFloatPointer
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_cc_squirreljme_jvm_Assembly_classInfoOfFloatPointer
(JNIEnv* env, jclass classy);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: classInfoOfInteger
* Signature: ()Lcc/squirreljme/jvm/ClassInfo;
*/
JNIEXPORT jobject JNICALL Java_cc_squirreljme_jvm_Assembly_classInfoOfInteger
(JNIEnv* env, jclass classy);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: classInfoOfIntegerPointer
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_cc_squirreljme_jvm_Assembly_classInfoOfIntegerPointer
(JNIEnv* env, jclass classy);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: classInfoOfLong
* Signature: ()Lcc/squirreljme/jvm/ClassInfo;
*/
JNIEXPORT jobject JNICALL Java_cc_squirreljme_jvm_Assembly_classInfoOfLong
(JNIEnv* env, jclass classy);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: classInfoOfLongPointer
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_cc_squirreljme_jvm_Assembly_classInfoOfLongPointer
(JNIEnv* env, jclass classy);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: classInfoOfShort
* Signature: ()Lcc/squirreljme/jvm/ClassInfo;
*/
JNIEXPORT jobject JNICALL Java_cc_squirreljme_jvm_Assembly_classInfoOfShort
(JNIEnv* env, jclass classy);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: classInfoOfShortPointer
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_cc_squirreljme_jvm_Assembly_classInfoOfShortPointer
(JNIEnv* env, jclass classy);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: doublePack
......@@ -809,70 +681,6 @@ JNIEXPORT void JNICALL Java_cc_squirreljme_jvm_Assembly_monitorOwnerSetAtomic__L
JNIEXPORT void JNICALL Java_cc_squirreljme_jvm_Assembly_monitorOwnerSetAtomic__Ljava_lang_Object_2Ljava_lang_Thread_2
(JNIEnv* env, jclass classy, jobject, jobject);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: objectGetClassInfo
* Signature: (J)Lcc/squirreljme/jvm/ClassInfo;
*/
JNIEXPORT jobject JNICALL Java_cc_squirreljme_jvm_Assembly_objectGetClassInfo__J
(JNIEnv* env, jclass classy, jlong);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: objectGetClassInfo
* Signature: (Ljava/lang/Object;)Lcc/squirreljme/jvm/ClassInfo;
*/
JNIEXPORT jobject JNICALL Java_cc_squirreljme_jvm_Assembly_objectGetClassInfo__Ljava_lang_Object_2
(JNIEnv* env, jclass classy, jobject);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: objectGetClassInfoPointer
* Signature: (J)J
*/
JNIEXPORT jlong JNICALL Java_cc_squirreljme_jvm_Assembly_objectGetClassInfoPointer__J
(JNIEnv* env, jclass classy, jlong);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: objectGetClassInfoPointer
* Signature: (Ljava/lang/Object;)J
*/
JNIEXPORT jlong JNICALL Java_cc_squirreljme_jvm_Assembly_objectGetClassInfoPointer__Ljava_lang_Object_2
(JNIEnv* env, jclass classy, jobject);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: objectSetClassInfo
* Signature: (JJ)V
*/
JNIEXPORT void JNICALL Java_cc_squirreljme_jvm_Assembly_objectSetClassInfo__JJ
(JNIEnv* env, jclass classy, jlong, jlong);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: objectSetClassInfo
* Signature: (Ljava/lang/Object;J)V
*/
JNIEXPORT void JNICALL Java_cc_squirreljme_jvm_Assembly_objectSetClassInfo__Ljava_lang_Object_2J
(JNIEnv* env, jclass classy, jobject, jlong);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: objectSetClassInfo
* Signature: (JLcc/squirreljme/jvm/ClassInfo;)V
*/
JNIEXPORT void JNICALL Java_cc_squirreljme_jvm_Assembly_objectSetClassInfo__JLcc_squirreljme_jvm_ClassInfo_2
(JNIEnv* env, jclass classy, jlong, jobject);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: objectSetClassInfo
* Signature: (Ljava/lang/Object;Lcc/squirreljme/jvm/ClassInfo;)V
*/
JNIEXPORT void JNICALL Java_cc_squirreljme_jvm_Assembly_objectSetClassInfo__Ljava_lang_Object_2Lcc_squirreljme_jvm_ClassInfo_2
(JNIEnv* env, jclass classy, jobject, jobject);
/*
* Class: cc_squirreljme_jvm_Assembly
* Method: objectToPointer
......
......@@ -30,13 +30,37 @@ import java.util.Objects;
*/
public final class EmulatedJarPackageShelf
{
/** Library path property. */
private static final String LIB_PATH_PROPERTY =
"squirreljme.hosted.libraries";
/** Cache of our own classpath. */
private static JarPackageBracket[] _CLASSPATH_CACHE;
/** Cache of loaded libraries. */
private static JarPackageBracket[] _LIB_CACHE;
/**
* Returns our classpath.
*
* @return Our classpath.
* @since 2021/06/24
*/
public static JarPackageBracket[] classPath()
{
// Use single cache for it, if available
JarPackageBracket[] rv = EmulatedJarPackageShelf._CLASSPATH_CACHE;
if (rv != null)
return rv.clone();
// Use the system property to know our true classpath
String paths = System.getProperty(EmulatedTaskShelf.RUN_CLASSPATH);
if (paths != null)
rv = EmulatedJarPackageShelf.__loadPaths(paths);
else
rv = new JarPackageBracket[0];
// Store cache for later usages
EmulatedJarPackageShelf._CLASSPATH_CACHE = rv;
return rv.clone();
}
/**
* Returns the libraries which are available to the virtual machine.
*
......@@ -53,36 +77,11 @@ public final class EmulatedJarPackageShelf
// For hosted VMs, the libraries are stored in a system property so
// that they can be accessed.
String paths = System.getProperty(
EmulatedJarPackageShelf.LIB_PATH_PROPERTY);
EmulatedTaskShelf.AVAILABLE_LIBRARIES);
if (paths != null)
{
List<JarPackageBracket> fill = new ArrayList<>();
for (int at = 0, next;; at = next + 1)
{
// Get the segment from this section
next = paths.indexOf(File.pathSeparatorChar, at + 1);
String segment = (next < 0 ? paths.substring(at) :
paths.substring(at, next));
Path segPath = Paths.get(segment);
// Are we filling a JAR or filling random file data?
VMClassLibrary vmLib;
if (JarClassLibrary.isJar(segment))
vmLib = new JarClassLibrary(segPath);
rv = EmulatedJarPackageShelf.__loadPaths(paths);
else
vmLib = new DataContainerLibrary(segPath);
// Wrap class library container
fill.add(new EmulatedJarPackageBracket(vmLib));
// Processing no more
if (next < 0)
break;
}
// Store them all
rv = fill.toArray(new JarPackageBracket[fill.size()]);
}
rv = new JarPackageBracket[0];
// Store cache for later usages
EmulatedJarPackageShelf._LIB_CACHE = rv;
......@@ -127,4 +126,41 @@ public final class EmulatedJarPackageShelf
return ((EmulatedJarPackageBracket)__jar).openResource(__rc);
}
/**
* Loads paths from the given JAR set.
*