Skip to content

Commit

Permalink
feat: merge runtime-core and runtime-js packages into graalvm.
Browse files Browse the repository at this point in the history
Signed-off-by: Dario Valdespino <dvaldespino00@gmail.com>
  • Loading branch information
darvld committed Sep 25, 2023
1 parent 1546716 commit 0cecc57
Show file tree
Hide file tree
Showing 40 changed files with 185 additions and 765 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,26 @@
*/

@file:Suppress("MemberVisibilityCanBePrivate")
@file:OptIn(DelicateElideApi::class)

package elide.runtime.gvm.internals

import com.fasterxml.jackson.databind.ObjectMapper
import elide.annotations.Inject
import elide.runtime.gvm.internals.context.ContextManager
import elide.runtime.core.DelicateElideApi
import elide.runtime.core.PolyglotContext
import elide.runtime.core.PolyglotEngine
import elide.runtime.core.PolyglotEngineConfiguration
import elide.vm.annotations.Polyglot
import org.graalvm.polyglot.Engine
import kotlinx.coroutines.test.runTest
import org.graalvm.polyglot.PolyglotException
import org.graalvm.polyglot.Value
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.assertThrows
import java.nio.charset.StandardCharsets
import java.util.concurrent.atomic.AtomicReference
import kotlinx.coroutines.test.runTest
import org.graalvm.polyglot.Context
import org.intellij.lang.annotations.Language
import org.junit.jupiter.api.Assertions
import java.util.concurrent.Callable
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicReference
import java.util.function.Function
import org.graalvm.polyglot.Context as VMContext

/** Base implementation of a test which can spawn VM contexts, and execute tests within them. */
abstract class AbstractDualTest {
Expand All @@ -42,7 +41,7 @@ abstract class AbstractDualTest {
return requireNotNull(AbstractDualTest::class.java.getResource(path)) {
"failed to locate resource at $path"
}.readText(
StandardCharsets.UTF_8
StandardCharsets.UTF_8,
)
}

Expand Down Expand Up @@ -178,11 +177,11 @@ abstract class AbstractDualTest {
is Value -> if (value.isBoolean) {
value.asBoolean()
} else error(
"Guest value '$value' is not a boolean"
"Guest value '$value' is not a boolean",
)

else -> error(
"Value '$value' is not a boolean"
"Value '$value' is not a boolean",
)
}
Assertions.assertTrue(
Expand All @@ -198,11 +197,11 @@ abstract class AbstractDualTest {
is Value -> if (value.isBoolean) {
value.asBoolean()
} else error(
"Guest value '$value' is not a boolean"
"Guest value '$value' is not a boolean",
)

else -> error(
"Value '$value' is not a boolean"
"Value '$value' is not a boolean",
)
}
Assertions.assertFalse(
Expand Down Expand Up @@ -242,7 +241,7 @@ abstract class AbstractDualTest {
Assertions.assertEquals(
other,
assertion.value,
message ?: "expected guest value equality mismatch (got `${assertion.value}`, but expected `$other`)"
message ?: "expected guest value equality mismatch (got `${assertion.value}`, but expected `$other`)",
)
}

Expand All @@ -251,7 +250,7 @@ abstract class AbstractDualTest {
Assertions.assertNotEquals(
assertion.value,
other,
message ?: "expected guest value inequality mismatch (got `${assertion.value}``)"
message ?: "expected guest value inequality mismatch (got `${assertion.value}``)",
)
}

Expand All @@ -261,7 +260,7 @@ abstract class AbstractDualTest {
is Value -> if (value.canExecute()) {
{ value.executeVoid() }
} else error(
"Guest value is not executable, cannot execute failure test"
"Guest value is not executable, cannot execute failure test",
)

is Runnable -> {
Expand All @@ -288,51 +287,40 @@ abstract class AbstractDualTest {
}
}

/** @return Initialized and exclusively-owned context for use with this test. */
protected abstract fun buildContext(engine: Engine, conf: (VMContext.Builder.() -> Unit)?): VMContext.Builder
/** A [PolyglotEngine] used to acquire context instances for testing, configurable trough [configureEngine]. */
protected val engine: PolyglotEngine by lazy { PolyglotEngine(::configureEngine) }

/** @return Initialized and exclusively-owned context for use with this test. */
protected abstract fun <V : Any> withContext(op: VMContext.() -> V): V
/** Configure the [engine] used to acquire contexts passed to [withContext]. */
protected open fun configureEngine(config: PolyglotEngineConfiguration) {
// nothing by default
}

/** @return Initialized and exclusively-owned context for use with this test. */
protected abstract fun <V : Any> withContext(op: VMContext.() -> V, conf: (VMContext.Builder.() -> Unit)?): V
/** Acquire an exclusive [PolyglotContext] instance from the [engine] and use it with a given [block] of code. */
protected open fun <T> withContext(block: PolyglotContext.() -> T): T {
return block(engine.acquire())
}

/** @return Execute a guest script with the subject intrinsics bound. */
protected abstract fun executeGuest(bind: Boolean = true, op: VMContext.() -> String): GuestTestExecution
protected abstract fun executeGuest(bind: Boolean = true, op: PolyglotContext.() -> String): GuestTestExecution

/** Single test execution within the scope of a guest VM. */
inner class GuestTestExecution(
private val builder: (VMContext.Builder.() -> Unit)?,
val factory: (VMContext.() -> Unit) -> Unit,
val test: VMContext.() -> Value?
val factory: (PolyglotContext.() -> Unit) -> Unit,
val test: PolyglotContext.() -> Value?
) {
constructor (
factory: (VMContext.() -> Unit) -> Unit,
test: VMContext.() -> Value?
) : this(
null,
factory,
test = test
)

// Return value, if any.
private val returnValue: AtomicReference<Value?> = AtomicReference(null)

// Set the return value from a test execution.
fun setReturnValue(value: Value): Unit = returnValue.set(value)

// Use the provided `builder` or generate one that just builds the context without changing it.
internal fun builder(): VMContext.Builder.() -> Unit {
return builder ?: { /* no-op */ }
}

// Retrieve the return value from a test execution.
fun returnValue(): Value? = returnValue.get()

/** After guest execution concludes, execute the provided [assertions] against the test context. */
fun thenAssert(
allowFailure: Boolean = false,
assertions: (VMContext.(GuestTestExecution) -> Unit)? = null,
assertions: (PolyglotContext.(GuestTestExecution) -> Unit)? = null,
) = factory {
if (allowFailure) {
failsWith<Throwable> {
Expand All @@ -349,7 +337,7 @@ abstract class AbstractDualTest {

/** After guest execution concludes, execute the provided [assertions] against the test context. */
inline fun <reified X : Throwable> failsWith(
noinline assertions: (VMContext.(GuestTestExecution) -> Unit)? = null
noinline assertions: (PolyglotContext.(GuestTestExecution) -> Unit)? = null
) = factory {
val exc = assertThrows<Throwable> {
val result = test.invoke(this)
Expand All @@ -364,13 +352,13 @@ abstract class AbstractDualTest {
is PolyglotException -> if (exc.isHostException) {
assert(exc.asHostException() is X) {
"Invalid exception type '${exc::class.simpleName}' raised " +
"(expected '${X::class.java.simpleName}')"
"(expected '${X::class.java.simpleName}')"
}
}

else -> throw AssertionError(
"Invalid exception type '${exc::class.simpleName}' raised " +
"(expected '${X::class.java.simpleName}')"
"(expected '${X::class.java.simpleName}')",
)
}
}
Expand All @@ -393,15 +381,15 @@ abstract class AbstractDualTest {
*
* @param guestOperation Operation to run on the guest.
*/
abstract fun guest(guestOperation: VMContext.() -> String)
abstract fun guest(guestOperation: PolyglotContext.() -> String)

/**
* Wire together the guest-side of a dual test, but defer for additional assertions.
*
* @param guestOperation Operation to run on the guest.
* @return Guest test execution control proxy.
*/
abstract fun thenRun(guestOperation: VMContext.() -> String): GuestTestExecution
abstract fun thenRun(guestOperation: PolyglotContext.() -> String): GuestTestExecution
}

// Run the provided `op` on the host, and the provided `guest` via `executeGuest`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@
*/

@file:Suppress("JSUnresolvedVariable")
@file:OptIn(DelicateElideApi::class)

package elide.runtime.gvm.internals.intrinsics.js.base64

import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.CsvSource
import elide.annotations.Inject
import elide.runtime.core.DelicateElideApi
import elide.runtime.gvm.internals.js.AbstractJsIntrinsicTest
import elide.testing.annotations.Test
import elide.testing.annotations.TestCase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
*/

@file:Suppress("JSUnresolvedVariable")
@file:OptIn(DelicateElideApi::class)

package elide.runtime.gvm.internals.intrinsics.js.console

import org.graalvm.polyglot.Value.asValue
import org.junit.jupiter.api.Assertions.assertNotNull
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.params.ParameterizedTest
Expand All @@ -26,6 +28,7 @@ import kotlin.test.assertEquals
import elide.annotations.Inject
import elide.runtime.LogLevel
import elide.runtime.Logger
import elide.runtime.core.DelicateElideApi
import elide.runtime.gvm.internals.js.AbstractJsIntrinsicTest
import elide.testing.annotations.Test
import elide.testing.annotations.TestCase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"JSVoidFunctionReturnValueUsed",
"JSCheckFunctionSignatures",
)
@file:OptIn(DelicateElideApi::class)

package elide.runtime.gvm.internals.intrinsics.js.crypto

Expand All @@ -27,6 +28,7 @@ import kotlin.test.assertFailsWith
import kotlin.test.assertNotEquals
import kotlin.test.assertNotNull
import elide.annotations.Inject
import elide.runtime.core.DelicateElideApi
import elide.runtime.gvm.internals.intrinsics.js.typed.UUIDValue
import elide.runtime.gvm.internals.js.AbstractJsIntrinsicTest
import elide.runtime.intrinsics.js.err.ValueError
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@
* License for the specific language governing permissions and limitations under the License.
*/

@file:OptIn(DelicateElideApi::class)

package elide.runtime.gvm.internals.intrinsics.js.express

import org.junit.jupiter.api.Test
import kotlin.test.assertIs
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
import elide.annotations.Inject
import elide.runtime.core.DelicateElideApi
import elide.runtime.gvm.internals.js.AbstractJsIntrinsicTest
import elide.testing.annotations.TestCase

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,24 @@
*/

@file:Suppress("JSUnresolvedFunction", "JSUnresolvedVariable")
@file:OptIn(DelicateElideApi::class)

package elide.runtime.gvm.internals.intrinsics.js.url

import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.CsvSource
import java.net.URI
import kotlin.test.assertFailsWith
import elide.annotations.Inject
import elide.runtime.core.DelicateElideApi
import elide.runtime.gvm.internals.intrinsics.js.url.URLIntrinsic.URLValue
import elide.runtime.gvm.internals.js.AbstractJsIntrinsicTest
import elide.runtime.intrinsics.js.err.TypeError
import elide.runtime.intrinsics.js.err.ValueError
import elide.testing.annotations.Test
import elide.testing.annotations.TestCase
import kotlin.test.Ignore
import org.graalvm.polyglot.Value.asValue
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.CsvSource
import java.net.URI
import kotlin.test.assertFailsWith

/** Tests for the intrinsic `URL` implementation provided by Elide. */
@Suppress("HttpUrlsUsage")
Expand Down
Loading

0 comments on commit 0cecc57

Please sign in to comment.