Move caching tests into a dedicated class
plus some tests refactorings
This commit is contained in:
+205
@@ -0,0 +1,205 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package kotlin.script.experimental.jvmhost.test
|
||||||
|
|
||||||
|
import junit.framework.TestCase
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Test
|
||||||
|
import java.io.File
|
||||||
|
import java.io.ObjectInputStream
|
||||||
|
import java.io.ObjectOutputStream
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.security.MessageDigest
|
||||||
|
import kotlin.script.experimental.api.*
|
||||||
|
import kotlin.script.experimental.host.toScriptSource
|
||||||
|
import kotlin.script.experimental.jvm.BasicJvmScriptEvaluator
|
||||||
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
|
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
|
||||||
|
import kotlin.script.experimental.jvmhost.*
|
||||||
|
import kotlin.script.templates.standard.SimpleScriptTemplate
|
||||||
|
|
||||||
|
class CachingTest : TestCase() {
|
||||||
|
|
||||||
|
val simpleScript = "val x = 1\nprintln(\"x = \$x\")"
|
||||||
|
val simpleScriptExpectedOutput = listOf("x = 1")
|
||||||
|
|
||||||
|
val scriptWithImport = "println(\"Hello from imported \$helloScriptName script!\")"
|
||||||
|
val scriptWithImportExpectedOutput = listOf("Hello from helloWithVal script!", "Hello from imported helloWithVal script!")
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testMemoryCache() {
|
||||||
|
val cache = SimpleMemoryScriptsCache()
|
||||||
|
checkWithCache(cache, simpleScript, simpleScriptExpectedOutput)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSimpleImportWithMemoryCache() {
|
||||||
|
val cache = SimpleMemoryScriptsCache()
|
||||||
|
checkWithCache(cache, scriptWithImport, scriptWithImportExpectedOutput) { makeSimpleConfigurationWithTestImport() }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFileCache() {
|
||||||
|
withTempDir("scriptingTestCache") { cacheDir ->
|
||||||
|
val cache = FileBasedScriptCache(cacheDir)
|
||||||
|
Assert.assertTrue(cache.baseDir.listFiles().isEmpty())
|
||||||
|
|
||||||
|
checkWithCache(cache, simpleScript, simpleScriptExpectedOutput)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSimpleImportWithFileCache() {
|
||||||
|
withTempDir("scriptingTestCache") { cacheDir ->
|
||||||
|
val cache = FileBasedScriptCache(cacheDir)
|
||||||
|
Assert.assertTrue(cache.baseDir.listFiles().isEmpty())
|
||||||
|
|
||||||
|
checkWithCache(cache, scriptWithImport, scriptWithImportExpectedOutput) { makeSimpleConfigurationWithTestImport() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkWithCache(
|
||||||
|
cache: ScriptingCacheWithCounters, script: String, expectedOutput: List<String>,
|
||||||
|
configurationBuilder: ScriptCompilationConfiguration.Builder.() -> Unit = {}
|
||||||
|
) {
|
||||||
|
val compiler = JvmScriptCompiler(defaultJvmScriptingHostConfiguration, cache = cache)
|
||||||
|
val evaluator = BasicJvmScriptEvaluator()
|
||||||
|
val host = BasicJvmScriptingHost(compiler = compiler, evaluator = evaluator)
|
||||||
|
|
||||||
|
val scriptCompilationConfiguration =
|
||||||
|
createJvmCompilationConfigurationFromTemplate<SimpleScriptTemplate>(body = configurationBuilder)
|
||||||
|
|
||||||
|
Assert.assertEquals(0, cache.storedScripts)
|
||||||
|
var compiledScript: CompiledScript<*>? = null
|
||||||
|
val output = captureOut {
|
||||||
|
runBlocking {
|
||||||
|
compiler(script.toScriptSource(), scriptCompilationConfiguration).onSuccess {
|
||||||
|
compiledScript = it
|
||||||
|
evaluator(it)
|
||||||
|
}.throwOnFailure()
|
||||||
|
}
|
||||||
|
}.lines()
|
||||||
|
Assert.assertEquals(expectedOutput, output)
|
||||||
|
Assert.assertEquals(1, cache.storedScripts)
|
||||||
|
Assert.assertEquals(0, cache.retrievedScripts)
|
||||||
|
|
||||||
|
val cachedScript = cache.get(script.toScriptSource(), scriptCompilationConfiguration)
|
||||||
|
Assert.assertNotNull(cachedScript)
|
||||||
|
Assert.assertEquals(1, cache.retrievedScripts)
|
||||||
|
|
||||||
|
val compiledScriptClassRes = runBlocking { compiledScript!!.getClass(null) }
|
||||||
|
val cachedScriptClassRes = runBlocking { cachedScript!!.getClass(null) }
|
||||||
|
|
||||||
|
val compiledScriptClass = compiledScriptClassRes.valueOrNull()
|
||||||
|
val cachedScriptClass = cachedScriptClassRes.valueOrNull()
|
||||||
|
|
||||||
|
Assert.assertEquals(compiledScriptClass!!.qualifiedName, cachedScriptClass!!.qualifiedName)
|
||||||
|
Assert.assertEquals(compiledScriptClass!!.supertypes, cachedScriptClass!!.supertypes)
|
||||||
|
|
||||||
|
val output2 = captureOut {
|
||||||
|
runBlocking {
|
||||||
|
evaluator(cachedScript!!).throwOnFailure()
|
||||||
|
}
|
||||||
|
}.lines()
|
||||||
|
Assert.assertEquals(output, output2)
|
||||||
|
|
||||||
|
val output3 = captureOut { evalScriptWithConfiguration(script, host, configurationBuilder).throwOnFailure() }.lines()
|
||||||
|
Assert.assertEquals(2, cache.retrievedScripts)
|
||||||
|
Assert.assertEquals(output, output3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private interface ScriptingCacheWithCounters : CompiledJvmScriptsCache {
|
||||||
|
|
||||||
|
val storedScripts: Int
|
||||||
|
val retrievedScripts: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SimpleMemoryScriptsCache : ScriptingCacheWithCounters {
|
||||||
|
|
||||||
|
internal val data = hashMapOf<Pair<SourceCode, ScriptCompilationConfiguration>, CompiledScript<*>>()
|
||||||
|
|
||||||
|
private var _storedScripts = 0
|
||||||
|
private var _retrievedScripts = 0
|
||||||
|
|
||||||
|
override val storedScripts: Int
|
||||||
|
get() = _storedScripts
|
||||||
|
|
||||||
|
override val retrievedScripts: Int
|
||||||
|
get() = _retrievedScripts
|
||||||
|
|
||||||
|
override fun get(script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration): CompiledScript<*>? =
|
||||||
|
data[script to scriptCompilationConfiguration]?.also { _retrievedScripts++ }
|
||||||
|
|
||||||
|
override fun store(
|
||||||
|
compiledScript: CompiledScript<*>,
|
||||||
|
script: SourceCode,
|
||||||
|
scriptCompilationConfiguration: ScriptCompilationConfiguration
|
||||||
|
) {
|
||||||
|
data[script to scriptCompilationConfiguration] = compiledScript
|
||||||
|
_storedScripts++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FileBasedScriptCache(val baseDir: File) : ScriptingCacheWithCounters {
|
||||||
|
|
||||||
|
override fun get(script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration): CompiledScript<*>? {
|
||||||
|
val file = File(baseDir, uniqueScriptHash(script, scriptCompilationConfiguration))
|
||||||
|
return if (!file.exists()) null else file.readCompiledScript(scriptCompilationConfiguration)?.also { retrievedScripts++ }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun store(
|
||||||
|
compiledScript: CompiledScript<*>,
|
||||||
|
script: SourceCode,
|
||||||
|
scriptCompilationConfiguration: ScriptCompilationConfiguration
|
||||||
|
) {
|
||||||
|
val file = File(baseDir, uniqueScriptHash(script, scriptCompilationConfiguration))
|
||||||
|
file.outputStream().use { fs ->
|
||||||
|
ObjectOutputStream(fs).use { os ->
|
||||||
|
os.writeObject(compiledScript)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
storedScripts++
|
||||||
|
}
|
||||||
|
|
||||||
|
override var storedScripts: Int = 0
|
||||||
|
private set
|
||||||
|
|
||||||
|
override var retrievedScripts: Int = 0
|
||||||
|
private set
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun uniqueScriptHash(script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration): String {
|
||||||
|
val digestWrapper = MessageDigest.getInstance("MD5")
|
||||||
|
digestWrapper.update(script.text.toByteArray())
|
||||||
|
scriptCompilationConfiguration.entries().sortedBy { it.key.name }.forEach {
|
||||||
|
digestWrapper.update(it.key.name.toByteArray())
|
||||||
|
digestWrapper.update(it.value.toString().toByteArray())
|
||||||
|
}
|
||||||
|
return digestWrapper.digest().toHexString()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun File.readCompiledScript(scriptCompilationConfiguration: ScriptCompilationConfiguration): CompiledScript<*> {
|
||||||
|
return inputStream().use { fs ->
|
||||||
|
ObjectInputStream(fs).use {
|
||||||
|
it.readObject() as KJvmCompiledScript<*>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ByteArray.toHexString(): String = joinToString("", transform = { "%02x".format(it) })
|
||||||
|
|
||||||
|
private fun <R> withTempDir(keyName: String = "tmp", body: (File) -> R) {
|
||||||
|
val tempDir = Files.createTempDirectory(keyName).toFile()
|
||||||
|
try {
|
||||||
|
body(tempDir)
|
||||||
|
} finally {
|
||||||
|
tempDir.deleteRecursively()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+21
-201
@@ -18,7 +18,6 @@ import java.io.*
|
|||||||
import java.lang.RuntimeException
|
import java.lang.RuntimeException
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.security.MessageDigest
|
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import java.util.jar.JarFile
|
import java.util.jar.JarFile
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
@@ -26,7 +25,6 @@ import kotlin.script.experimental.api.*
|
|||||||
import kotlin.script.experimental.host.BasicScriptingHost
|
import kotlin.script.experimental.host.BasicScriptingHost
|
||||||
import kotlin.script.experimental.host.FileBasedScriptSource
|
import kotlin.script.experimental.host.FileBasedScriptSource
|
||||||
import kotlin.script.experimental.host.toScriptSource
|
import kotlin.script.experimental.host.toScriptSource
|
||||||
import kotlin.script.experimental.jvm.BasicJvmScriptEvaluator
|
|
||||||
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||||
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
|
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
|
||||||
import kotlin.script.experimental.jvm.updateClasspath
|
import kotlin.script.experimental.jvm.updateClasspath
|
||||||
@@ -162,21 +160,7 @@ class ScriptingHostTest : TestCase() {
|
|||||||
checkInvokeMain(null) // isolated
|
checkInvokeMain(null) // isolated
|
||||||
checkInvokeMain(Thread.currentThread().contextClassLoader)
|
checkInvokeMain(Thread.currentThread().contextClassLoader)
|
||||||
|
|
||||||
val javaExecutable = File(File(System.getProperty("java.home"), "bin"), "java")
|
val outputFromProcess = runScriptFromJar(outJar)
|
||||||
val args = listOf(javaExecutable.absolutePath, "-jar", outJar.path)
|
|
||||||
val processBuilder = ProcessBuilder(args)
|
|
||||||
processBuilder.redirectErrorStream(true)
|
|
||||||
val outputFromProcess = run {
|
|
||||||
val process = processBuilder.start()
|
|
||||||
process.waitFor(10, TimeUnit.SECONDS)
|
|
||||||
val out = process.inputStream.reader().readText()
|
|
||||||
if (process.isAlive) {
|
|
||||||
process.destroyForcibly()
|
|
||||||
"Error: timeout, killing script process\n$out"
|
|
||||||
} else {
|
|
||||||
out
|
|
||||||
}
|
|
||||||
}.trim()
|
|
||||||
Assert.assertEquals(greeting, outputFromProcess)
|
Assert.assertEquals(greeting, outputFromProcess)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,103 +340,6 @@ class ScriptingHostTest : TestCase() {
|
|||||||
jvmTargetTestImpl("9", 53)
|
jvmTargetTestImpl("9", 53)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testMemoryCache() {
|
|
||||||
val script = "val x = 1\nprintln(\"x = \$x\")"
|
|
||||||
val expectedOutput = listOf("x = 1")
|
|
||||||
val cache = SimpleMemoryScriptsCache()
|
|
||||||
checkWithCache(cache, script, expectedOutput)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testSimpleImportWithMemoryCache() {
|
|
||||||
val script = "println(\"Hello from imported \$helloScriptName script!\")"
|
|
||||||
val expectedOutput = listOf("Hello from helloWithVal script!", "Hello from imported helloWithVal script!")
|
|
||||||
val cache = SimpleMemoryScriptsCache()
|
|
||||||
checkWithCache(cache, script, expectedOutput) { makeSimpleConfigurationWithTestImport() }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testFileCache() {
|
|
||||||
val script = "val x = 1\nprintln(\"x = \$x\")"
|
|
||||||
val expectedOutput = listOf("x = 1")
|
|
||||||
val cacheDir = Files.createTempDirectory("scriptingTestCache").toFile()
|
|
||||||
try {
|
|
||||||
val cache = FileBasedScriptCache(cacheDir)
|
|
||||||
Assert.assertTrue(cache.baseDir.listFiles().isEmpty())
|
|
||||||
|
|
||||||
checkWithCache(cache, script, expectedOutput)
|
|
||||||
} finally {
|
|
||||||
cacheDir.deleteRecursively()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testSimpleImportWithFileCache() {
|
|
||||||
val script = "println(\"Hello from imported \$helloScriptName script!\")"
|
|
||||||
val expectedOutput = listOf("Hello from helloWithVal script!", "Hello from imported helloWithVal script!")
|
|
||||||
val cacheDir = Files.createTempDirectory("scriptingTestCache").toFile()
|
|
||||||
try {
|
|
||||||
val cache = FileBasedScriptCache(cacheDir)
|
|
||||||
Assert.assertTrue(cache.baseDir.listFiles().isEmpty())
|
|
||||||
|
|
||||||
checkWithCache(cache, script, expectedOutput) { makeSimpleConfigurationWithTestImport() }
|
|
||||||
} finally {
|
|
||||||
cacheDir.deleteRecursively()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkWithCache(
|
|
||||||
cache: ScriptingCacheWithCounters, script: String, expectedOutput: List<String>,
|
|
||||||
configurationBuilder: ScriptCompilationConfiguration.Builder.() -> Unit = {}
|
|
||||||
) {
|
|
||||||
val compiler = JvmScriptCompiler(defaultJvmScriptingHostConfiguration, cache = cache)
|
|
||||||
val evaluator = BasicJvmScriptEvaluator()
|
|
||||||
val host = BasicJvmScriptingHost(compiler = compiler, evaluator = evaluator)
|
|
||||||
|
|
||||||
val scriptCompilationConfiguration =
|
|
||||||
createJvmCompilationConfigurationFromTemplate<SimpleScriptTemplate>(body = configurationBuilder)
|
|
||||||
|
|
||||||
Assert.assertEquals(0, cache.storedScripts)
|
|
||||||
var compiledScript: CompiledScript<*>? = null
|
|
||||||
val output = captureOut {
|
|
||||||
runBlocking {
|
|
||||||
compiler(script.toScriptSource(), scriptCompilationConfiguration).onSuccess {
|
|
||||||
compiledScript = it
|
|
||||||
evaluator(it)
|
|
||||||
}.throwOnFailure()
|
|
||||||
}
|
|
||||||
}.lines()
|
|
||||||
Assert.assertEquals(expectedOutput, output)
|
|
||||||
Assert.assertEquals(1, cache.storedScripts)
|
|
||||||
Assert.assertEquals(0, cache.retrievedScripts)
|
|
||||||
|
|
||||||
val cachedScript = cache.get(script.toScriptSource(), scriptCompilationConfiguration)
|
|
||||||
Assert.assertNotNull(cachedScript)
|
|
||||||
Assert.assertEquals(1, cache.retrievedScripts)
|
|
||||||
|
|
||||||
val compiledScriptClassRes = runBlocking { compiledScript!!.getClass(null) }
|
|
||||||
val cachedScriptClassRes = runBlocking { cachedScript!!.getClass(null) }
|
|
||||||
|
|
||||||
val compiledScriptClass = compiledScriptClassRes.valueOrNull()
|
|
||||||
val cachedScriptClass = cachedScriptClassRes.valueOrNull()
|
|
||||||
|
|
||||||
Assert.assertEquals(compiledScriptClass!!.qualifiedName, cachedScriptClass!!.qualifiedName)
|
|
||||||
Assert.assertEquals(compiledScriptClass!!.supertypes, cachedScriptClass!!.supertypes)
|
|
||||||
|
|
||||||
val output2 = captureOut {
|
|
||||||
runBlocking {
|
|
||||||
evaluator(cachedScript!!).throwOnFailure()
|
|
||||||
}
|
|
||||||
}.lines()
|
|
||||||
Assert.assertEquals(output, output2)
|
|
||||||
|
|
||||||
val output3 = captureOut { evalScriptWithConfiguration(script, host, configurationBuilder).throwOnFailure() }.lines()
|
|
||||||
Assert.assertEquals(2, cache.retrievedScripts)
|
|
||||||
Assert.assertEquals(output, output3)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testCompiledScriptClassLoader() {
|
fun testCompiledScriptClassLoader() {
|
||||||
val script = "val x = 1"
|
val script = "val x = 1"
|
||||||
@@ -486,6 +373,24 @@ class ScriptingHostTest : TestCase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun runScriptFromJar(jar: File): String {
|
||||||
|
val javaExecutable = File(File(System.getProperty("java.home"), "bin"), "java")
|
||||||
|
val args = listOf(javaExecutable.absolutePath, "-jar", jar.path)
|
||||||
|
val processBuilder = ProcessBuilder(args)
|
||||||
|
processBuilder.redirectErrorStream(true)
|
||||||
|
return run {
|
||||||
|
val process = processBuilder.start()
|
||||||
|
process.waitFor(10, TimeUnit.SECONDS)
|
||||||
|
val out = process.inputStream.reader().readText()
|
||||||
|
if (process.isAlive) {
|
||||||
|
process.destroyForcibly()
|
||||||
|
"Error: timeout, killing script process\n$out"
|
||||||
|
} else {
|
||||||
|
out
|
||||||
|
}
|
||||||
|
}.trim()
|
||||||
|
}
|
||||||
|
|
||||||
fun <T> ResultWithDiagnostics<T>.throwOnFailure(): ResultWithDiagnostics<T> = apply {
|
fun <T> ResultWithDiagnostics<T>.throwOnFailure(): ResultWithDiagnostics<T> = apply {
|
||||||
if (this is ResultWithDiagnostics.Failure) {
|
if (this is ResultWithDiagnostics.Failure) {
|
||||||
val firstExceptionFromReports = reports.find { it.exception != null }?.exception
|
val firstExceptionFromReports = reports.find { it.exception != null }?.exception
|
||||||
@@ -506,7 +411,7 @@ private fun evalScriptWithResult(
|
|||||||
): ResultValue =
|
): ResultValue =
|
||||||
evalScriptWithConfiguration(script, host, body).throwOnFailure().valueOrNull()!!.returnValue
|
evalScriptWithConfiguration(script, host, body).throwOnFailure().valueOrNull()!!.returnValue
|
||||||
|
|
||||||
private fun evalScriptWithConfiguration(
|
internal fun evalScriptWithConfiguration(
|
||||||
script: String,
|
script: String,
|
||||||
host: BasicScriptingHost = BasicJvmScriptingHost(),
|
host: BasicScriptingHost = BasicJvmScriptingHost(),
|
||||||
body: ScriptCompilationConfiguration.Builder.() -> Unit = {}
|
body: ScriptCompilationConfiguration.Builder.() -> Unit = {}
|
||||||
@@ -515,40 +420,7 @@ private fun evalScriptWithConfiguration(
|
|||||||
return host.eval(script.toScriptSource(), compilationConfiguration, null)
|
return host.eval(script.toScriptSource(), compilationConfiguration, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun ScriptCompilationConfiguration.Builder.makeSimpleConfigurationWithTestImport() {
|
||||||
private interface ScriptingCacheWithCounters : CompiledJvmScriptsCache {
|
|
||||||
|
|
||||||
val storedScripts: Int
|
|
||||||
val retrievedScripts: Int
|
|
||||||
}
|
|
||||||
|
|
||||||
private class SimpleMemoryScriptsCache : ScriptingCacheWithCounters {
|
|
||||||
|
|
||||||
internal val data = hashMapOf<Pair<SourceCode, ScriptCompilationConfiguration>, CompiledScript<*>>()
|
|
||||||
|
|
||||||
private var _storedScripts = 0
|
|
||||||
private var _retrievedScripts = 0
|
|
||||||
|
|
||||||
override val storedScripts: Int
|
|
||||||
get() = _storedScripts
|
|
||||||
|
|
||||||
override val retrievedScripts: Int
|
|
||||||
get() = _retrievedScripts
|
|
||||||
|
|
||||||
override fun get(script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration): CompiledScript<*>? =
|
|
||||||
data[script to scriptCompilationConfiguration]?.also { _retrievedScripts++ }
|
|
||||||
|
|
||||||
override fun store(
|
|
||||||
compiledScript: CompiledScript<*>,
|
|
||||||
script: SourceCode,
|
|
||||||
scriptCompilationConfiguration: ScriptCompilationConfiguration
|
|
||||||
) {
|
|
||||||
data[script to scriptCompilationConfiguration] = compiledScript
|
|
||||||
_storedScripts++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun ScriptCompilationConfiguration.Builder.makeSimpleConfigurationWithTestImport() {
|
|
||||||
refineConfiguration {
|
refineConfiguration {
|
||||||
beforeCompiling { ctx ->
|
beforeCompiling { ctx ->
|
||||||
val importedScript = File(ScriptingHostTest.TEST_DATA_DIR, "importTest/helloWithVal.kts")
|
val importedScript = File(ScriptingHostTest.TEST_DATA_DIR, "importTest/helloWithVal.kts")
|
||||||
@@ -563,58 +435,6 @@ private fun ScriptCompilationConfiguration.Builder.makeSimpleConfigurationWithTe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun File.readCompiledScript(scriptCompilationConfiguration: ScriptCompilationConfiguration): CompiledScript<*> {
|
|
||||||
return inputStream().use { fs ->
|
|
||||||
ObjectInputStream(fs).use {
|
|
||||||
it.readObject() as KJvmCompiledScript<*>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun ByteArray.toHexString(): String = joinToString("", transform = { "%02x".format(it) })
|
|
||||||
|
|
||||||
|
|
||||||
private class FileBasedScriptCache(val baseDir: File) : ScriptingCacheWithCounters {
|
|
||||||
|
|
||||||
internal fun uniqueHash(script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration): String {
|
|
||||||
val digestWrapper = MessageDigest.getInstance("MD5")
|
|
||||||
digestWrapper.update(script.text.toByteArray())
|
|
||||||
scriptCompilationConfiguration.entries().sortedBy { it.key.name }.forEach {
|
|
||||||
digestWrapper.update(it.key.name.toByteArray())
|
|
||||||
digestWrapper.update(it.value.toString().toByteArray())
|
|
||||||
}
|
|
||||||
return digestWrapper.digest().toHexString()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun get(script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration): CompiledScript<*>? {
|
|
||||||
val file = File(baseDir, uniqueHash(script, scriptCompilationConfiguration))
|
|
||||||
return if (!file.exists()) null else file.readCompiledScript(scriptCompilationConfiguration)?.also { _retrievedScripts++ }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun store(
|
|
||||||
compiledScript: CompiledScript<*>,
|
|
||||||
script: SourceCode,
|
|
||||||
scriptCompilationConfiguration: ScriptCompilationConfiguration
|
|
||||||
) {
|
|
||||||
val file = File(baseDir, uniqueHash(script, scriptCompilationConfiguration))
|
|
||||||
file.outputStream().use { fs ->
|
|
||||||
ObjectOutputStream(fs).use { os ->
|
|
||||||
os.writeObject(compiledScript)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_storedScripts++
|
|
||||||
}
|
|
||||||
|
|
||||||
private var _storedScripts = 0
|
|
||||||
private var _retrievedScripts = 0
|
|
||||||
|
|
||||||
override val storedScripts: Int
|
|
||||||
get() = _storedScripts
|
|
||||||
|
|
||||||
override val retrievedScripts: Int
|
|
||||||
get() = _retrievedScripts
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun captureOut(body: () -> Unit): String = captureOutAndErr(body).first
|
internal fun captureOut(body: () -> Unit): String = captureOutAndErr(body).first
|
||||||
|
|
||||||
internal fun captureOutAndErr(body: () -> Unit): Pair<String, String> {
|
internal fun captureOutAndErr(body: () -> Unit): Pair<String, String> {
|
||||||
|
|||||||
Reference in New Issue
Block a user