Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP SDL FFI #2263

Merged
merged 5 commits into from
Jul 5, 2024
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
1 change: 0 additions & 1 deletion buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ dependencies {
implementation(libs.proguard.gradle)
implementation(libs.gson)
implementation(libs.gradle.publish.plugin)
implementation(libs.korlibs.serialization)
implementation(libs.kotlin.gradle.plugin)
implementation(libs.android.build.gradle)
testImplementation(libs.junit)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package korlibs.korge.gradle

import groovy.text.*
import korlibs.*
import korlibs.io.serialization.yaml.*
import korlibs.korge.gradle.processor.*
import korlibs.korge.gradle.targets.*
import korlibs.korge.gradle.targets.android.*
Expand Down Expand Up @@ -178,7 +177,7 @@ open class KorgeExtension(
fun loadYaml(file: File) {
val korgeYamlString = file.takeIfExists()?.readText() ?: return
try {
val info = korlibs.io.serialization.yaml.Yaml.read(korgeYamlString).dyn
val info = korlibs.korge.gradle.util.Yaml.read(korgeYamlString).dyn
info["id"].toStringOrNull()?.let { this.id = it }

author(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
package korlibs.korge.gradle.targets.js

import korlibs.korge.gradle.targets.*
import korlibs.korge.gradle.util.*
import org.gradle.api.*
import org.gradle.api.internal.tasks.testing.*
import org.gradle.api.tasks.*
import org.gradle.api.tasks.testing.*
import java.io.*

fun Project.configureDenoTest() {
afterEvaluate {
if (tasks.findByName("compileTestDevelopmentExecutableKotlinJs") == null) return@afterEvaluate

val jsDenoTest = project.tasks.createThis<DenoTestTask>("jsDenoTest") {
}
}
}


fun Project.configureDenoRun() {
afterEvaluate {
if (tasks.findByName("compileDevelopmentExecutableKotlinJs") == null) return@afterEvaluate

val baseRunFileNameBase = project.fullPathName().trim(':').replace(':', '-')
val baseRunFileName = "$baseRunFileNameBase.mjs"
val runFile = File(rootProject.rootDir, "build/js/packages/$baseRunFileNameBase/kotlin/$baseRunFileName")

val runDeno = project.tasks.createThis<Exec>("runDeno") {
group = GROUP_KORGE_RUN
dependsOn("compileDevelopmentExecutableKotlinJs")
commandLine("deno", "run", "--unstable-ffi", "--unstable-webgpu", "-A", runFile)
workingDir(runFile.parentFile.absolutePath)
}

val packageDeno = project.tasks.createThis<Exec>("packageDeno") {
group = GROUP_KORGE_PACKAGE
dependsOn("compileDevelopmentExecutableKotlinJs")
commandLine("deno", "compile", "--unstable-ffi", "--unstable-webgpu", "-A", runFile)
workingDir(runFile.parentFile.absolutePath)
}
}
}

open class DenoTestTask : AbstractTestTask() {
//open class DenoTestTask : KotlinTest() {

//var isDryRun by org.jetbrains.kotlin.gradle.utils.property { false }

init {
this.group = "verification"
this.dependsOn("compileTestDevelopmentExecutableKotlinJs")
}

//@Option(option = "tests", description = "Specify tests to execute as a filter")
//@Input
//var tests: String = ""

init {
this.reports {
it.junitXml.outputLocation.set(project.file("build/test-results/jsDenoTest/"))
it.html.outputLocation.set(project.file("build/reports/tests/jsDenoTest/"))
}
binaryResultsDirectory.set(project.file("build/test-results/jsDenoTest/binary"))
//reports.enabledReports["junitXml"]!!.optional
//reports.junitXml.outputLocation.opt
//reports.enabledReports.clear()
//reports.junitXml.outputLocation.set(project.file("build/deno-test-results"))
}

override fun createTestExecuter(): TestExecuter<out TestExecutionSpec> {
return DenoTestExecuter(this.project, this.filter)
}
//override fun createTestExecuter(): TestExecuter<out TestExecutionSpec> = TODO()
override fun createTestExecutionSpec(): TestExecutionSpec = DenoTestExecutionSpec()

init {
outputs.upToDateWhen { false }
}

class DenoTestExecuter(val project: Project, val filter: TestFilter) : TestExecuter<DenoTestExecutionSpec> {
private fun Project.fullPathName(): String {
//KotlinTest
if (this.parent == null) return this.name
return this.parent!!.fullPathName() + ":" + this.name
}

override fun execute(testExecutionSpec: DenoTestExecutionSpec, testResultProcessor: TestResultProcessor) {
val baseTestFileNameBase = this.project.fullPathName().trim(':').replace(':', '-') + "-test"
val baseTestFileName = "$baseTestFileNameBase.mjs"
val runFile = File(this.project.rootProject.rootDir, "build/js/packages/$baseTestFileNameBase/kotlin/$baseTestFileName.deno.mjs")

runFile.parentFile.mkdirs()
runFile.writeText(
//language=js
"""
var describeStack = []
globalThis.describe = (name, callback) => { describeStack.push(name); try { callback() } finally { describeStack.pop() } }
globalThis.it = (name, callback) => { return Deno.test({ name: describeStack.join(".") + "." + name, fn: callback}) }
globalThis.xit = (name, callback) => { return Deno.test({ name: describeStack.join(".") + "." + name, ignore: true, fn: callback}) }
function exists(path) { try { Deno.statSync(path); return true } catch (e) { return false } }
// Polyfill required for kotlinx-coroutines that detects window
window.postMessage = (message, targetOrigin) => { const ev = new Event('message'); ev.source = window; ev.data = message; window.dispatchEvent(ev); }
const file = './${baseTestFileName}';
if (exists(file)) await import(file)
""".trimIndent())

//testResultProcessor.started()
val process = ProcessBuilder(buildList<String> {
add("deno")
add("test")
add("--unstable-ffi")
add("--unstable-webgpu")
add("-A")
if (filter.includePatterns.isEmpty()) {
add("--filter=${filter.includePatterns.joinToString(",")}")
}
add("--junit-path=${project.file("build/test-results/jsDenoTest/junit.xml").absolutePath}")
add(runFile.absolutePath)
}).directory(runFile.parentFile)
.start()
var id = 0
val buffered = process.inputStream.bufferedReader()
var capturingOutput = false
var currentTestId: String? = null
var currentTestExtra: String = "ok"
var failedCount = 0

fun flush() {
if (currentTestId != null) {
try {
val type = when {
currentTestExtra.contains("skip", ignoreCase = true) || currentTestExtra.contains("ignored", ignoreCase = true) -> TestResult.ResultType.SKIPPED
currentTestExtra.contains("error", ignoreCase = true) || currentTestExtra.contains("failed", ignoreCase = true) -> TestResult.ResultType.FAILURE
currentTestExtra.contains("ok", ignoreCase = true) -> TestResult.ResultType.SUCCESS
else -> TestResult.ResultType.SUCCESS
}
if (type == TestResult.ResultType.FAILURE) {
testResultProcessor.output(currentTestId, DefaultTestOutputEvent(TestOutputEvent.Destination.StdErr, "FAILED\n"))
testResultProcessor.failure(currentTestId, DefaultTestFailure.fromTestFrameworkFailure(Exception("FAILED").also { it.stackTrace = arrayOf() }, null))
failedCount++
}
testResultProcessor.completed(currentTestId, TestCompleteEvent(System.currentTimeMillis(), type))
} catch (e: Throwable) {
//System.err.println("COMPLETED_ERROR: ${e}")
e.printStackTrace()
}
currentTestId = null
}
}

testResultProcessor.started(DefaultTestSuiteDescriptor("deno", "deno"), TestStartEvent(System.currentTimeMillis()))

for (line in buffered.lines()) {
println("::: $line")
when {
line == "------- output -------" -> {
capturingOutput = true
}
line == "----- output end -----" -> {
capturingOutput = false
}
capturingOutput -> {
testResultProcessor.output(currentTestId, DefaultTestOutputEvent(TestOutputEvent.Destination.StdOut, "$line\n"))
}
line.contains("...") -> {
//DefaultNestedTestSuiteDescriptor()
flush()
val (name, extra) = line.split("...").map { it.trim() }
//currentTestId = "$name${id++}"
currentTestId = "deno.myid${id++}"
//val demo = CompositeId("Unit", "Name${id++}")
//val descriptor = DefaultTestMethodDescriptor(currentTestId, name.substringBeforeLast('.'), name.substringAfterLast('.'))

val descriptor = DefaultTestMethodDescriptor(currentTestId, name.substringBeforeLast('.'), name)
currentTestExtra = extra
testResultProcessor.started(
descriptor,
TestStartEvent(System.currentTimeMillis())
)
}
}
}
flush()

testResultProcessor.completed("deno", TestCompleteEvent(System.currentTimeMillis(), if (failedCount == 0) TestResult.ResultType.SUCCESS else TestResult.ResultType.FAILURE))

process.waitFor()
System.err.print(process.errorStream.readBytes().decodeToString())
}

override fun stopNow() {
}
}

class DenoTestExecutionSpec : TestExecutionSpec
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,67 +64,6 @@ fun Project.fullPathName(): String {
return this.parent!!.fullPathName() + ":" + this.name
}

fun Project.configureDenoTest() {
afterEvaluate {
if (tasks.findByName("compileTestDevelopmentExecutableKotlinJs") == null) return@afterEvaluate

val jsDenoTest = project.tasks.createThis<Exec>("jsDenoTest") {
group = "verification"

dependsOn("compileTestDevelopmentExecutableKotlinJs")

val baseTestFileNameBase = project.fullPathName().trim(':').replace(':', '-') + "-test"
val baseTestFileName = "$baseTestFileNameBase.mjs"

val runFile = File(rootProject.rootDir, "build/js/packages/$baseTestFileNameBase/kotlin/$baseTestFileName.deno.mjs")

commandLine("deno", "test", "--unstable-ffi", "--unstable-webgpu", "-A", runFile)
workingDir(runFile.parentFile.absolutePath)

doFirst {
runFile.parentFile.mkdirs()
runFile.writeText(
//language=js
"""
var describeStack = []
globalThis.describe = (name, callback) => { describeStack.push(name); try { callback() } finally { describeStack.pop() } }
globalThis.it = (name, callback) => { return Deno.test({ name: describeStack.join(".") + "." + name, fn: callback}) }
globalThis.xit = (name, callback) => { return Deno.test({ name: describeStack.join(".") + "." + name, ignore: true, fn: callback}) }
function exists(path) { try { Deno.statSync(path); return true } catch (e) { return false } }
// Polyfill required for kotlinx-coroutines that detects window
window.postMessage = (message, targetOrigin) => { const ev = new Event('message'); ev.source = window; ev.data = message; window.dispatchEvent(ev); }
const file = './$baseTestFileName';
if (exists(file)) await import(file)
""".trimIndent())
}
}
}
}

fun Project.configureDenoRun() {
afterEvaluate {
if (tasks.findByName("compileDevelopmentExecutableKotlinJs") == null) return@afterEvaluate

val baseRunFileNameBase = project.fullPathName().trim(':').replace(':', '-')
val baseRunFileName = "$baseRunFileNameBase.mjs"
val runFile = File(rootProject.rootDir, "build/js/packages/$baseRunFileNameBase/kotlin/$baseRunFileName")

val runDeno = project.tasks.createThis<Exec>("runDeno") {
group = GROUP_KORGE_RUN
dependsOn("compileDevelopmentExecutableKotlinJs")
commandLine("deno", "run", "--unstable-ffi", "--unstable-webgpu", "-A", runFile)
workingDir(runFile.parentFile.absolutePath)
}

val packageDeno = project.tasks.createThis<Exec>("packageDeno") {
group = GROUP_KORGE_PACKAGE
dependsOn("compileDevelopmentExecutableKotlinJs")
commandLine("deno", "compile", "--unstable-ffi", "--unstable-webgpu", "-A", runFile)
workingDir(runFile.parentFile.absolutePath)
}
}
}

fun Project.configureJavascriptRun() {
val runJsRelease = project.tasks.createThis<RunJsServer>(name = "runJsRelease") {
group = GROUP_KORGE_RUN
Expand Down
Loading