Use new kotlin.io.path API in tests
This commit is contained in:
+9
-5
@@ -27,6 +27,9 @@ import org.junit.Assert
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileWriter
|
import java.io.FileWriter
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
import kotlin.io.path.ExperimentalPathApi
|
||||||
|
import kotlin.io.path.Path
|
||||||
|
import kotlin.io.path.createTempDirectory
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
data class ConfigurationKey(val kind: ConfigurationKind, val jdkKind: TestJdkKind, val configuration: String)
|
data class ConfigurationKey(val kind: ConfigurationKind, val jdkKind: TestJdkKind, val configuration: String)
|
||||||
@@ -345,14 +348,15 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
|
|||||||
FileWriter(file).use { fw -> fw.write("sdk.dir=$sdkRoot") }
|
FileWriter(file).use { fw -> fw.write("sdk.dir=$sdkRoot") }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPathApi::class)
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
val tmpFolder = createTempDir()
|
val tmpFolder = createTempDirectory().toAbsolutePath().toString()
|
||||||
println("Created temporary folder for android tests: " + tmpFolder.absolutePath)
|
println("Created temporary folder for android tests: $tmpFolder")
|
||||||
val rootFolder = File("")
|
val rootFolder = Path("").toAbsolutePath().toString()
|
||||||
val pathManager = PathManager(rootFolder.absolutePath, tmpFolder.absolutePath)
|
val pathManager = PathManager(rootFolder, tmpFolder)
|
||||||
generate(pathManager, true)
|
generate(pathManager, true)
|
||||||
println("Android test project is generated into " + tmpFolder.absolutePath + " folder")
|
println("Android test project is generated into $tmpFolder folder")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,10 @@ import java.io.ByteArrayOutputStream
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.PrintStream
|
import java.io.PrintStream
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
|
import java.nio.file.Path
|
||||||
|
import kotlin.io.path.*
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPathApi::class)
|
||||||
class CompilerApiTest : KotlinIntegrationTestBase() {
|
class CompilerApiTest : KotlinIntegrationTestBase() {
|
||||||
|
|
||||||
private val compilerLibDir = getCompilerLib()
|
private val compilerLibDir = getCompilerLib()
|
||||||
@@ -119,7 +122,7 @@ class CompilerApiTest : KotlinIntegrationTestBase() {
|
|||||||
verbose = true,
|
verbose = true,
|
||||||
reportPerf = true)
|
reportPerf = true)
|
||||||
|
|
||||||
val logFile = createTempFile("kotlin-daemon-test.", ".log")
|
val logFile: Path = createTempFile("kotlin-daemon-test.", ".log")
|
||||||
|
|
||||||
val daemonJVMOptions = configureDaemonJVMOptions("D$COMPILE_DAEMON_LOG_PATH_PROPERTY=\"${logFile.loggerCompatiblePath}\"",
|
val daemonJVMOptions = configureDaemonJVMOptions("D$COMPILE_DAEMON_LOG_PATH_PROPERTY=\"${logFile.loggerCompatiblePath}\"",
|
||||||
inheritMemoryLimits = false, inheritOtherJvmOptions = false, inheritAdditionalProperties = false)
|
inheritMemoryLimits = false, inheritOtherJvmOptions = false, inheritAdditionalProperties = false)
|
||||||
@@ -137,7 +140,8 @@ class CompilerApiTest : KotlinIntegrationTestBase() {
|
|||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
KotlinCompilerClient.shutdownCompileService(compilerId, daemonOptions)
|
KotlinCompilerClient.shutdownCompileService(compilerId, daemonOptions)
|
||||||
logFile.delete()
|
runCatching { logFile.deleteIfExists() }
|
||||||
|
.onFailure { e -> println("Failed to delete log file: $e") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,7 +162,7 @@ class CompilerApiTest : KotlinIntegrationTestBase() {
|
|||||||
verbose = true,
|
verbose = true,
|
||||||
reportPerf = true)
|
reportPerf = true)
|
||||||
|
|
||||||
val logFile = createTempFile("kotlin-daemon-test.", ".log")
|
val logFile: Path = createTempFile("kotlin-daemon-test.", ".log")
|
||||||
|
|
||||||
val daemonJVMOptions = configureDaemonJVMOptions("D$COMPILE_DAEMON_LOG_PATH_PROPERTY=\"${logFile.loggerCompatiblePath}\"",
|
val daemonJVMOptions = configureDaemonJVMOptions("D$COMPILE_DAEMON_LOG_PATH_PROPERTY=\"${logFile.loggerCompatiblePath}\"",
|
||||||
inheritMemoryLimits = false, inheritOtherJvmOptions = false, inheritAdditionalProperties = false)
|
inheritMemoryLimits = false, inheritOtherJvmOptions = false, inheritAdditionalProperties = false)
|
||||||
@@ -174,7 +178,8 @@ class CompilerApiTest : KotlinIntegrationTestBase() {
|
|||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
KotlinCompilerClient.shutdownCompileService(compilerId, daemonOptions)
|
KotlinCompilerClient.shutdownCompileService(compilerId, daemonOptions)
|
||||||
logFile.delete()
|
runCatching { logFile.deleteIfExists() }
|
||||||
|
.onFailure { e -> println("Failed to delete log file: $e") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,10 +36,13 @@ import java.lang.management.ManagementFactory
|
|||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
|
import java.nio.file.Path
|
||||||
import java.rmi.server.UnicastRemoteObject
|
import java.rmi.server.UnicastRemoteObject
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
import kotlin.io.path.ExperimentalPathApi
|
||||||
|
import kotlin.io.path.invariantSeparatorsPath
|
||||||
import kotlin.script.dependencies.Environment
|
import kotlin.script.dependencies.Environment
|
||||||
import kotlin.script.dependencies.ScriptContents
|
import kotlin.script.dependencies.ScriptContents
|
||||||
import kotlin.script.experimental.dependencies.DependenciesResolver
|
import kotlin.script.experimental.dependencies.DependenciesResolver
|
||||||
@@ -997,9 +1000,12 @@ internal inline fun withLogFile(prefix: String, suffix: String = ".log", printLo
|
|||||||
// if file path is given in windows form (using backslash as a separator); the reason is unknown
|
// if file path is given in windows form (using backslash as a separator); the reason is unknown
|
||||||
// this function makes a path with forward slashed, that works on windows too
|
// this function makes a path with forward slashed, that works on windows too
|
||||||
internal val File.loggerCompatiblePath: String
|
internal val File.loggerCompatiblePath: String
|
||||||
get() =
|
get() = invariantSeparatorsPath
|
||||||
if (OSKind.current == OSKind.Windows) absolutePath.replace('\\', '/')
|
|
||||||
else absolutePath
|
@OptIn(ExperimentalPathApi::class)
|
||||||
|
internal val Path.loggerCompatiblePath: String
|
||||||
|
get() = invariantSeparatorsPath
|
||||||
|
|
||||||
|
|
||||||
open class TestKotlinScriptDummyDependenciesResolver : DependenciesResolver {
|
open class TestKotlinScriptDummyDependenciesResolver : DependenciesResolver {
|
||||||
|
|
||||||
|
|||||||
+6
-3
@@ -28,13 +28,16 @@ import org.junit.Assert
|
|||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
|
import java.nio.file.Path
|
||||||
import java.util.logging.LogManager
|
import java.util.logging.LogManager
|
||||||
import java.util.logging.Logger
|
import java.util.logging.Logger
|
||||||
|
import kotlin.io.path.*
|
||||||
|
|
||||||
private val logFiles = arrayListOf<String>()
|
private val logFiles = arrayListOf<String>()
|
||||||
|
|
||||||
// TODO: remove ignore annotation from tests.
|
// TODO: remove ignore annotation from tests.
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPathApi::class)
|
||||||
@RunWith(IgnoreAll::class)
|
@RunWith(IgnoreAll::class)
|
||||||
class CompilerApiTest : KotlinIntegrationTestBase() {
|
class CompilerApiTest : KotlinIntegrationTestBase() {
|
||||||
|
|
||||||
@@ -43,7 +46,7 @@ class CompilerApiTest : KotlinIntegrationTestBase() {
|
|||||||
|
|
||||||
private val compilerLibDir = getCompilerLib()
|
private val compilerLibDir = getCompilerLib()
|
||||||
|
|
||||||
private fun createNewLogFile(): File {
|
private fun createNewLogFile(): Path {
|
||||||
println("creating logFile")
|
println("creating logFile")
|
||||||
val newLogFile = createTempFile("kotlin-daemon-experimental-test.", ".log")
|
val newLogFile = createTempFile("kotlin-daemon-experimental-test.", ".log")
|
||||||
println("logFile created (${newLogFile.loggerCompatiblePath})")
|
println("logFile created (${newLogFile.loggerCompatiblePath})")
|
||||||
@@ -51,7 +54,7 @@ class CompilerApiTest : KotlinIntegrationTestBase() {
|
|||||||
return newLogFile
|
return newLogFile
|
||||||
}
|
}
|
||||||
|
|
||||||
private val currentLogFile: File by lazy {
|
private val currentLogFile: Path by lazy {
|
||||||
val newLogFile = createNewLogFile()
|
val newLogFile = createNewLogFile()
|
||||||
val cfg: String =
|
val cfg: String =
|
||||||
"handlers = java.util.logging.FileHandler\n" +
|
"handlers = java.util.logging.FileHandler\n" +
|
||||||
@@ -67,7 +70,7 @@ class CompilerApiTest : KotlinIntegrationTestBase() {
|
|||||||
newLogFile
|
newLogFile
|
||||||
}
|
}
|
||||||
|
|
||||||
private val externalLogFile: File by lazy { createNewLogFile() }
|
private val externalLogFile: Path by lazy { createNewLogFile() }
|
||||||
|
|
||||||
private val log by lazy {
|
private val log by lazy {
|
||||||
currentLogFile
|
currentLogFile
|
||||||
|
|||||||
+14
-18
@@ -3,6 +3,8 @@
|
|||||||
* that can be found in the license/LICENSE.txt file.
|
* that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@file:OptIn(ExperimentalPathApi::class)
|
||||||
|
|
||||||
package org.jetbrains.kotlin.daemon.experimental.integration
|
package org.jetbrains.kotlin.daemon.experimental.integration
|
||||||
|
|
||||||
import junit.framework.TestCase
|
import junit.framework.TestCase
|
||||||
@@ -38,6 +40,7 @@ import java.net.URL
|
|||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
import java.nio.channels.ClosedChannelException
|
import java.nio.channels.ClosedChannelException
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
|
import java.nio.file.Path
|
||||||
import java.rmi.ConnectException
|
import java.rmi.ConnectException
|
||||||
import java.rmi.ConnectIOException
|
import java.rmi.ConnectIOException
|
||||||
import java.rmi.UnmarshalException
|
import java.rmi.UnmarshalException
|
||||||
@@ -46,6 +49,7 @@ import java.util.concurrent.CountDownLatch
|
|||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import java.util.logging.LogManager
|
import java.util.logging.LogManager
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
import kotlin.io.path.*
|
||||||
import kotlin.script.dependencies.Environment
|
import kotlin.script.dependencies.Environment
|
||||||
import kotlin.script.dependencies.ScriptContents
|
import kotlin.script.dependencies.ScriptContents
|
||||||
import kotlin.script.experimental.dependencies.DependenciesResolver
|
import kotlin.script.experimental.dependencies.DependenciesResolver
|
||||||
@@ -64,7 +68,7 @@ class CompilerDaemonTest : KotlinIntegrationTestBase() {
|
|||||||
|
|
||||||
val kotlinCompilerClientInstance = KotlinCompilerDaemonClient.instantiate(DaemonProtocolVariant.SOCKETS)
|
val kotlinCompilerClientInstance = KotlinCompilerDaemonClient.instantiate(DaemonProtocolVariant.SOCKETS)
|
||||||
|
|
||||||
private fun createNewLogFile(): File {
|
private fun createNewLogFile(): Path {
|
||||||
println("creating logFile")
|
println("creating logFile")
|
||||||
val newLogFile = createTempFile("kotlin-daemon-experimental-test.", ".log")
|
val newLogFile = createTempFile("kotlin-daemon-experimental-test.", ".log")
|
||||||
println("logFile created (${newLogFile.loggerCompatiblePath})")
|
println("logFile created (${newLogFile.loggerCompatiblePath})")
|
||||||
@@ -595,8 +599,8 @@ class CompilerDaemonTest : KotlinIntegrationTestBase() {
|
|||||||
shutdownDelayMilliseconds = 1,
|
shutdownDelayMilliseconds = 1,
|
||||||
runFilesPath = File(tmpdir, getTestName(true)).absolutePath
|
runFilesPath = File(tmpdir, getTestName(true)).absolutePath
|
||||||
)
|
)
|
||||||
val clientFlag = createTempFile(getTestName(true), "-client.alive")
|
val clientFlag = createTempFile(getTestName(true), "-client.alive").toFile()
|
||||||
val sessionFlag = createTempFile(getTestName(true), "-session.alive")
|
val sessionFlag = createTempFile(getTestName(true), "-session.alive").toFile()
|
||||||
try {
|
try {
|
||||||
withLogFile("kotlin-daemon-test") { logFile ->
|
withLogFile("kotlin-daemon-test") { logFile ->
|
||||||
val daemonJVMOptions = makeTestDaemonJvmOptions(logFile)
|
val daemonJVMOptions = makeTestDaemonJvmOptions(logFile)
|
||||||
@@ -635,8 +639,8 @@ class CompilerDaemonTest : KotlinIntegrationTestBase() {
|
|||||||
shutdownDelayMilliseconds = 1,
|
shutdownDelayMilliseconds = 1,
|
||||||
runFilesPath = File(tmpdir, getTestName(true)).absolutePath
|
runFilesPath = File(tmpdir, getTestName(true)).absolutePath
|
||||||
)
|
)
|
||||||
val clientFlag = createTempFile(getTestName(true), "-client.alive")
|
val clientFlag = createTempFile(getTestName(true), "-client.alive").toFile()
|
||||||
val sessionFlag = createTempFile(getTestName(true), "-session.alive")
|
val sessionFlag = createTempFile(getTestName(true), "-session.alive").toFile()
|
||||||
try {
|
try {
|
||||||
withLogFile("kotlin-daemon-test") { logFile ->
|
withLogFile("kotlin-daemon-test") { logFile ->
|
||||||
val daemonJVMOptions = makeTestDaemonJvmOptions(logFile)
|
val daemonJVMOptions = makeTestDaemonJvmOptions(logFile)
|
||||||
@@ -678,8 +682,8 @@ class CompilerDaemonTest : KotlinIntegrationTestBase() {
|
|||||||
shutdownDelayMilliseconds = 3000,
|
shutdownDelayMilliseconds = 3000,
|
||||||
runFilesPath = File(tmpdir, getTestName(true)).absolutePath
|
runFilesPath = File(tmpdir, getTestName(true)).absolutePath
|
||||||
)
|
)
|
||||||
val clientFlag = createTempFile(getTestName(true), "-client.alive")
|
val clientFlag = createTempFile(getTestName(true), "-client.alive").toFile()
|
||||||
val clientFlag2 = createTempFile(getTestName(true), "-client.alive")
|
val clientFlag2 = createTempFile(getTestName(true), "-client.alive").toFile()
|
||||||
try {
|
try {
|
||||||
withLogFile("kotlin-daemon-test") { logFile ->
|
withLogFile("kotlin-daemon-test") { logFile ->
|
||||||
val daemonJVMOptions = makeTestDaemonJvmOptions(logFile)
|
val daemonJVMOptions = makeTestDaemonJvmOptions(logFile)
|
||||||
@@ -769,8 +773,7 @@ class CompilerDaemonTest : KotlinIntegrationTestBase() {
|
|||||||
assertEquals("Compilation failed:\n$resOutput", 0, resCode)
|
assertEquals("Compilation failed:\n$resOutput", 0, resCode)
|
||||||
println("OK")
|
println("OK")
|
||||||
} finally {
|
} finally {
|
||||||
if (clientAliveFile.exists())
|
clientAliveFile.deleteIfExists()
|
||||||
clientAliveFile.delete()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1427,7 +1430,7 @@ fun restoreSystemProperty(propertyName: String, backupValue: String?) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal inline fun withFlagFile(prefix: String, suffix: String? = null, body: (File) -> Unit) {
|
internal inline fun withFlagFile(prefix: String, suffix: String? = null, body: (File) -> Unit) {
|
||||||
val file = createTempFile(prefix, suffix)
|
val file = createTempFile(prefix, suffix).toFile()
|
||||||
try {
|
try {
|
||||||
body(file)
|
body(file)
|
||||||
} finally {
|
} finally {
|
||||||
@@ -1436,7 +1439,7 @@ internal inline fun withFlagFile(prefix: String, suffix: String? = null, body: (
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal inline fun withLogFile(prefix: String, suffix: String = ".log", printLogOnException: Boolean = true, body: (File) -> Unit) {
|
internal inline fun withLogFile(prefix: String, suffix: String = ".log", printLogOnException: Boolean = true, body: (File) -> Unit) {
|
||||||
val logFile = createTempFile(prefix, suffix)
|
val logFile = createTempFile(prefix, suffix).toFile()
|
||||||
println("LOG FILE : ${logFile.path}")
|
println("LOG FILE : ${logFile.path}")
|
||||||
try {
|
try {
|
||||||
body(logFile)
|
body(logFile)
|
||||||
@@ -1449,13 +1452,6 @@ internal inline fun withLogFile(prefix: String, suffix: String = ".log", printLo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// java.util.Logger used in the daemon silently forgets to log into a file specified in the config on Windows,
|
|
||||||
// if file path is given in windows form (using backslash as a separator); the reason is unknown
|
|
||||||
// this function makes a path with forward slashed, that works on windows too
|
|
||||||
internal val File.loggerCompatiblePath: String
|
|
||||||
get() =
|
|
||||||
if (OSKind.current == OSKind.Windows) absolutePath.replace('\\', '/')
|
|
||||||
else absolutePath
|
|
||||||
|
|
||||||
open class TestKotlinScriptDummyDependenciesResolver : DependenciesResolver {
|
open class TestKotlinScriptDummyDependenciesResolver : DependenciesResolver {
|
||||||
|
|
||||||
|
|||||||
+2
@@ -24,6 +24,7 @@ import java.io.ObjectInputStream
|
|||||||
import java.io.ObjectOutputStream
|
import java.io.ObjectOutputStream
|
||||||
import java.net.InetSocketAddress
|
import java.net.InetSocketAddress
|
||||||
import java.util.logging.Logger
|
import java.util.logging.Logger
|
||||||
|
import kotlin.io.path.*
|
||||||
|
|
||||||
@OptIn(KtorExperimentalAPI::class)
|
@OptIn(KtorExperimentalAPI::class)
|
||||||
class TestServer(val serverPort: Int = 6999) {
|
class TestServer(val serverPort: Int = 6999) {
|
||||||
@@ -44,6 +45,7 @@ val testServer = TestServer()
|
|||||||
|
|
||||||
@RunWith(IgnoreAll::class)
|
@RunWith(IgnoreAll::class)
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
@OptIn(ExperimentalPathApi::class)
|
||||||
class ClientSerializationTest : KotlinIntegrationTestBase() {
|
class ClientSerializationTest : KotlinIntegrationTestBase() {
|
||||||
|
|
||||||
val file = createTempFile()
|
val file = createTempFile()
|
||||||
|
|||||||
+6
-3
@@ -31,11 +31,14 @@ import java.io.ByteArrayOutputStream
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.PrintStream
|
import java.io.PrintStream
|
||||||
|
import java.nio.file.Path
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.logging.LogManager
|
import java.util.logging.LogManager
|
||||||
import java.util.logging.Logger
|
import java.util.logging.Logger
|
||||||
import kotlin.concurrent.schedule
|
import kotlin.concurrent.schedule
|
||||||
|
import kotlin.io.path.*
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPathApi::class)
|
||||||
@RunWith(IgnoreAll::class)
|
@RunWith(IgnoreAll::class)
|
||||||
class ConnectionsTest : KotlinIntegrationTestBase() {
|
class ConnectionsTest : KotlinIntegrationTestBase() {
|
||||||
|
|
||||||
@@ -247,15 +250,15 @@ class ConnectionsTest : KotlinIntegrationTestBase() {
|
|||||||
extraAction
|
extraAction
|
||||||
)
|
)
|
||||||
|
|
||||||
private val clientFiles = arrayListOf<File>()
|
private val clientFiles = mutableListOf<Path>()
|
||||||
private fun generateClient(): String {
|
private fun generateClient(): String {
|
||||||
val file = createTempFile(getTestName(true), ".alive")
|
val file = createTempFile(getTestName(true), ".alive")
|
||||||
clientFiles.add(file)
|
clientFiles.add(file)
|
||||||
return file.absolutePath
|
return file.toAbsolutePath().toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun deleteClients() {
|
private fun deleteClients() {
|
||||||
clientFiles.forEach { it.delete() }
|
clientFiles.forEach { it.deleteIfExists() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun endTest() {
|
private fun endTest() {
|
||||||
|
|||||||
+2
-1
@@ -22,6 +22,7 @@ import org.junit.Assert
|
|||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.nio.file.Files
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class BuildDiffsStorageTest {
|
class BuildDiffsStorageTest {
|
||||||
@@ -30,7 +31,7 @@ class BuildDiffsStorageTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
storageFile = File.createTempFile("BuildDiffsStorageTest", "storage")
|
storageFile = Files.createTempFile("BuildDiffsStorageTest", "storage").toFile()
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
testCompile(kotlinStdlib("jdk8"))
|
||||||
testCompile(project(":kotlin-scripting-compiler"))
|
testCompile(project(":kotlin-scripting-compiler"))
|
||||||
testCompile(project(":core:descriptors"))
|
testCompile(project(":core:descriptors"))
|
||||||
testCompile(project(":core:descriptors.jvm"))
|
testCompile(project(":core:descriptors.jvm"))
|
||||||
|
|||||||
+3
-1
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.test.MockLibraryUtil
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
import kotlin.io.path.*
|
||||||
|
|
||||||
const val JSPECIFY_NULLNESS_MISMATCH_MARK = "jspecify_nullness_mismatch"
|
const val JSPECIFY_NULLNESS_MISMATCH_MARK = "jspecify_nullness_mismatch"
|
||||||
|
|
||||||
@@ -30,6 +31,7 @@ abstract class AbstractJspecifyAnnotationsTest : AbstractDiagnosticsTest() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPathApi::class)
|
||||||
override fun doTest(filePath: String) {
|
override fun doTest(filePath: String) {
|
||||||
val ktSourceCode = File(filePath).readText()
|
val ktSourceCode = File(filePath).readText()
|
||||||
val javaSourcesFilename = javaSourcesPathRegex.matcher(ktSourceCode).also { it.find() }.group(1)
|
val javaSourcesFilename = javaSourcesPathRegex.matcher(ktSourceCode).also { it.find() }.group(1)
|
||||||
@@ -51,7 +53,7 @@ abstract class AbstractJspecifyAnnotationsTest : AbstractDiagnosticsTest() {
|
|||||||
appendLine("// FILE: main.kt\n$ktSourceCode")
|
appendLine("// FILE: main.kt\n$ktSourceCode")
|
||||||
}
|
}
|
||||||
|
|
||||||
super.doTest(createTempFile().apply { writeText(mergedSourceCode) }.path)
|
super.doTest(createTempFile().apply { writeText(mergedSourceCode) }.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun makeJavaClassesPublicAndSeparatedByFiles(javaCode: String): String {
|
private fun makeJavaClassesPublicAndSeparatedByFiles(javaCode: String): String {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
|||||||
import kotlin.Pair;
|
import kotlin.Pair;
|
||||||
import kotlin.collections.CollectionsKt;
|
import kotlin.collections.CollectionsKt;
|
||||||
import kotlin.io.FilesKt;
|
import kotlin.io.FilesKt;
|
||||||
|
import kotlin.io.path.PathsKt;
|
||||||
import kotlin.text.Charsets;
|
import kotlin.text.Charsets;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.checkers.AbstractForeignAnnotationsTestKt;
|
import org.jetbrains.kotlin.checkers.AbstractForeignAnnotationsTestKt;
|
||||||
@@ -37,12 +38,17 @@ import org.jetbrains.kotlin.test.CompilerTestUtil;
|
|||||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils;
|
import org.jetbrains.kotlin.test.InTextDirectivesUtils;
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||||
import org.jetbrains.kotlin.test.TestCaseWithTmpdir;
|
import org.jetbrains.kotlin.test.TestCaseWithTmpdir;
|
||||||
|
import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
|
||||||
import org.jetbrains.kotlin.utils.JsMetadataVersion;
|
import org.jetbrains.kotlin.utils.JsMetadataVersion;
|
||||||
import org.jetbrains.kotlin.utils.PathUtil;
|
import org.jetbrains.kotlin.utils.PathUtil;
|
||||||
import org.jetbrains.kotlin.utils.StringsKt;
|
import org.jetbrains.kotlin.utils.StringsKt;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -232,15 +238,20 @@ public abstract class AbstractCliTest extends TestCaseWithTmpdir {
|
|||||||
@NotNull String tempDir
|
@NotNull String tempDir
|
||||||
) {
|
) {
|
||||||
String filePath = kotlin.text.StringsKt.substringAfter(argument, argumentPrefix, argument);
|
String filePath = kotlin.text.StringsKt.substringAfter(argument, argumentPrefix, argument);
|
||||||
File file = new File(filePath);
|
Path file = Paths.get(filePath);
|
||||||
if (!file.exists()) return argument;
|
if (!Files.exists(file)) return argument;
|
||||||
|
|
||||||
File result = FilesKt.createTempFile(file.getAbsolutePath(), tempFileSuffix, new File(tempDir));
|
try {
|
||||||
String oldContent = FilesKt.readText(file, Charsets.UTF_8);
|
Path result = Files.createTempFile(Paths.get(tempDir), file.getFileName().toString(), tempFileSuffix);
|
||||||
String newContent = replaceTestPaths(oldContent, testDataDir, tempDir);
|
String oldContent = PathsKt.readText(file, Charsets.UTF_8);
|
||||||
FilesKt.writeText(result, newContent, Charsets.UTF_8);
|
String newContent = replaceTestPaths(oldContent, testDataDir, tempDir);
|
||||||
|
PathsKt.writeText(result, newContent, Charsets.UTF_8);
|
||||||
|
|
||||||
return argumentPrefix + result.getAbsolutePath();
|
return argumentPrefix + result.toAbsolutePath();
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
throw ExceptionUtilsKt.rethrow(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String replaceTestPaths(@NotNull String str, @NotNull String testDataDir, @NotNull String tempDir) {
|
private static String replaceTestPaths(@NotNull String str, @NotNull String testDataDir, @NotNull String tempDir) {
|
||||||
|
|||||||
+8
-11
@@ -10,27 +10,24 @@ import org.gradle.internal.exceptions.LocationAwareException
|
|||||||
import org.gradle.internal.resource.UriTextResource
|
import org.gradle.internal.resource.UriTextResource
|
||||||
import org.jetbrains.kotlin.idea.scripting.gradle.importing.parsePositionFromException
|
import org.jetbrains.kotlin.idea.scripting.gradle.importing.parsePositionFromException
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.File
|
import kotlin.io.path.*
|
||||||
import java.io.PrintWriter
|
|
||||||
import java.io.StringWriter
|
|
||||||
import java.lang.RuntimeException
|
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertNotNull
|
import kotlin.test.assertNotNull
|
||||||
|
|
||||||
class KotlinDslScriptModelTest {
|
class KotlinDslScriptModelTest {
|
||||||
|
@OptIn(ExperimentalPathApi::class)
|
||||||
@Test
|
@Test
|
||||||
fun testExceptionPositionParsing() {
|
fun testExceptionPositionParsing() {
|
||||||
val file = File(createTempDir("kotlinDslTest"), "build.gradle.kts")
|
val file = createTempDirectory("kotlinDslTest") / "build.gradle.kts"
|
||||||
val line = 10
|
val line = 10
|
||||||
|
|
||||||
val mockScriptSource = TextResourceScriptSource(UriTextResource("build file", file))
|
val mockScriptSource = TextResourceScriptSource(UriTextResource("build file", file.toFile()))
|
||||||
val mockException = LocationAwareException(RuntimeException(), mockScriptSource, line)
|
val mockException = LocationAwareException(RuntimeException(), mockScriptSource, line)
|
||||||
val stringWriter = StringWriter()
|
val fromException = parsePositionFromException(mockException.stackTraceToString())
|
||||||
mockException.printStackTrace(PrintWriter(stringWriter))
|
|
||||||
|
|
||||||
val fromException = parsePositionFromException(stringWriter.toString())
|
|
||||||
assertNotNull(fromException, "Position should be parsed")
|
assertNotNull(fromException, "Position should be parsed")
|
||||||
assertEquals(fromException.first, file.absolutePath, "Wrong file name parsed")
|
assertEquals(fromException.first, file.toAbsolutePath().toString(), "Wrong file name parsed")
|
||||||
assertEquals(fromException.second.line, line, "Wrong line number parsed")
|
assertEquals(fromException.second.line, line, "Wrong line number parsed")
|
||||||
|
|
||||||
|
file.parent.deleteExisting()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,15 +7,16 @@ package org.jetbrains.kotlin.idea.perf.util
|
|||||||
|
|
||||||
import com.intellij.openapi.util.io.FileUtilRt
|
import com.intellij.openapi.util.io.FileUtilRt
|
||||||
import com.sun.management.HotSpotDiagnosticMXBean
|
import com.sun.management.HotSpotDiagnosticMXBean
|
||||||
import java.io.File
|
|
||||||
import java.io.FileInputStream
|
|
||||||
import java.io.FileOutputStream
|
|
||||||
import java.lang.management.ManagementFactory
|
import java.lang.management.ManagementFactory
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.Path
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.zip.ZipEntry
|
import java.util.zip.ZipEntry
|
||||||
import java.util.zip.ZipOutputStream
|
import java.util.zip.ZipOutputStream
|
||||||
|
import kotlin.io.path.*
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPathApi::class)
|
||||||
object HeapDumper {
|
object HeapDumper {
|
||||||
private const val HOTSPOT_BEAN_NAME = "com.sun.management:type=HotSpotDiagnostic"
|
private const val HOTSPOT_BEAN_NAME = "com.sun.management:type=HotSpotDiagnostic"
|
||||||
|
|
||||||
@@ -30,15 +31,15 @@ object HeapDumper {
|
|||||||
fun dumpHeap(fileNamePrefix: String, live: Boolean = true) {
|
fun dumpHeap(fileNamePrefix: String, live: Boolean = true) {
|
||||||
val format = SimpleDateFormat("yyyyMMdd-HHmmss")
|
val format = SimpleDateFormat("yyyyMMdd-HHmmss")
|
||||||
val timestamp = format.format(Date())
|
val timestamp = format.format(Date())
|
||||||
val tempFile = File.createTempFile(fileNamePrefix, ".hprof")
|
val tempFile = createTempFile(fileNamePrefix, ".hprof")
|
||||||
tempFile.delete()
|
tempFile.deleteIfExists()
|
||||||
val fileName = "build/$fileNamePrefix-$timestamp.hprof.zip"
|
val fileName = "build/$fileNamePrefix-$timestamp.hprof.zip"
|
||||||
logMessage { "Dumping a heap into $tempFile ..." }
|
logMessage { "Dumping a heap into $tempFile ..." }
|
||||||
try {
|
try {
|
||||||
hotspotMBean.dumpHeap(tempFile.toString(), live)
|
hotspotMBean.dumpHeap(tempFile.toString(), live)
|
||||||
logMessage { "Heap dump is $tempFile ready." }
|
logMessage { "Heap dump is $tempFile ready." }
|
||||||
|
|
||||||
zipFile(tempFile, File(fileName))
|
zipFile(tempFile, Path(fileName))
|
||||||
|
|
||||||
val testName = "Heap dump $timestamp"
|
val testName = "Heap dump $timestamp"
|
||||||
TeamCity.test(testName) {
|
TeamCity.test(testName) {
|
||||||
@@ -50,9 +51,9 @@ object HeapDumper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun zipFile(srcFile: File, targetFile: File) {
|
private fun zipFile(srcFile: Path, targetFile: Path) {
|
||||||
FileInputStream(srcFile).use { fis ->
|
srcFile.inputStream().use { fis ->
|
||||||
ZipOutputStream(FileOutputStream(targetFile)).use { os ->
|
ZipOutputStream(targetFile.outputStream()).use { os ->
|
||||||
os.putNextEntry(ZipEntry(srcFile.name))
|
os.putNextEntry(ZipEntry(srcFile.name))
|
||||||
FileUtilRt.copy(fis, os)
|
FileUtilRt.copy(fis, os)
|
||||||
os.closeEntry()
|
os.closeEntry()
|
||||||
|
|||||||
+4
-1
@@ -15,16 +15,19 @@ import org.jetbrains.kotlin.incremental.testingUtils.assertEqualDirectories
|
|||||||
import org.jetbrains.kotlin.jps.build.fixtures.EnableICFixture
|
import org.jetbrains.kotlin.jps.build.fixtures.EnableICFixture
|
||||||
import org.jetbrains.kotlin.jps.incremental.KotlinDataContainerTarget
|
import org.jetbrains.kotlin.jps.incremental.KotlinDataContainerTarget
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import kotlin.io.path.ExperimentalPathApi
|
||||||
|
import kotlin.io.path.createTempDirectory
|
||||||
import kotlin.reflect.KFunction1
|
import kotlin.reflect.KFunction1
|
||||||
|
|
||||||
class RelocatableJpsCachesTest : BaseKotlinJpsBuildTestCase() {
|
class RelocatableJpsCachesTest : BaseKotlinJpsBuildTestCase() {
|
||||||
private val enableICFixture = EnableICFixture()
|
private val enableICFixture = EnableICFixture()
|
||||||
private lateinit var workingDir: File
|
private lateinit var workingDir: File
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPathApi::class)
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
super.setUp()
|
super.setUp()
|
||||||
enableICFixture.setUp()
|
enableICFixture.setUp()
|
||||||
workingDir = createTempDir("RelocatableJpsCachesTest", getTestName(false))
|
workingDir = createTempDirectory("RelocatableJpsCachesTest-" + getTestName(false)).toFile()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun tearDown() {
|
override fun tearDown() {
|
||||||
|
|||||||
@@ -65,8 +65,10 @@ import org.junit.Before
|
|||||||
import org.junit.Ignore
|
import org.junit.Ignore
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import kotlin.io.path.*
|
||||||
import org.jetbrains.kotlin.konan.file.File as KonanFile
|
import org.jetbrains.kotlin.konan.file.File as KonanFile
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPathApi::class)
|
||||||
@Ignore
|
@Ignore
|
||||||
class GenerateIrRuntime {
|
class GenerateIrRuntime {
|
||||||
private val lookupTracker: LookupTracker = LookupTracker.DO_NOTHING
|
private val lookupTracker: LookupTracker = LookupTracker.DO_NOTHING
|
||||||
@@ -251,7 +253,7 @@ class GenerateIrRuntime {
|
|||||||
val irVersion = KlibIrVersion.INSTANCE.toString()
|
val irVersion = KlibIrVersion.INSTANCE.toString()
|
||||||
|
|
||||||
val versions = KotlinLibraryVersioning(libraryVersion, compilerVersion, abiVersion, metadataVersion, irVersion)
|
val versions = KotlinLibraryVersioning(libraryVersion, compilerVersion, abiVersion, metadataVersion, irVersion)
|
||||||
val file = createTempFile(directory = workingDir)
|
val file = createTempFile(directory = workingDir.toPath()).toFile()
|
||||||
val writer = KotlinLibraryOnlyIrWriter(file.absolutePath, "", versions, BuiltInsPlatform.JS, emptyList(), false)
|
val writer = KotlinLibraryOnlyIrWriter(file.absolutePath, "", versions, BuiltInsPlatform.JS, emptyList(), false)
|
||||||
val files = fullRuntimeSourceSet
|
val files = fullRuntimeSourceSet
|
||||||
val analysisResult = doFrontEnd(files)
|
val analysisResult = doFrontEnd(files)
|
||||||
@@ -273,7 +275,7 @@ class GenerateIrRuntime {
|
|||||||
val irVersion = KlibIrVersion.INSTANCE.toString()
|
val irVersion = KlibIrVersion.INSTANCE.toString()
|
||||||
|
|
||||||
val versions = KotlinLibraryVersioning(libraryVersion, compilerVersion, abiVersion, metadataVersion, irVersion)
|
val versions = KotlinLibraryVersioning(libraryVersion, compilerVersion, abiVersion, metadataVersion, irVersion)
|
||||||
val file = createTempFile(directory = workingDir)
|
val file = createTempFile(directory = workingDir.toPath()).toFile()
|
||||||
val writer = KotlinLibraryOnlyIrWriter(file.absolutePath, "", versions, BuiltInsPlatform.JS, emptyList(), true)
|
val writer = KotlinLibraryOnlyIrWriter(file.absolutePath, "", versions, BuiltInsPlatform.JS, emptyList(), true)
|
||||||
val files = fullRuntimeSourceSet
|
val files = fullRuntimeSourceSet
|
||||||
val analysisResult = doFrontEnd(files)
|
val analysisResult = doFrontEnd(files)
|
||||||
@@ -473,15 +475,16 @@ class GenerateIrRuntime {
|
|||||||
return psi2IrTranslator.generateModuleFragment(psi2IrContext, files, irProviders, emptyList(), null)
|
return psi2IrTranslator.generateModuleFragment(psi2IrContext, files, irProviders, emptyList(), null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPathApi::class)
|
||||||
private fun doSerializeModule(moduleFragment: IrModuleFragment, bindingContext: BindingContext, files: List<KtFile>, perFile: Boolean = false): String {
|
private fun doSerializeModule(moduleFragment: IrModuleFragment, bindingContext: BindingContext, files: List<KtFile>, perFile: Boolean = false): String {
|
||||||
val tmpKlibDir = createTempDir().also { it.deleteOnExit() }
|
val tmpKlibDir = createTempDirectory().also { it.toFile().deleteOnExit() }.toString()
|
||||||
serializeModuleIntoKlib(
|
serializeModuleIntoKlib(
|
||||||
moduleName,
|
moduleName,
|
||||||
project,
|
project,
|
||||||
configuration,
|
configuration,
|
||||||
bindingContext,
|
bindingContext,
|
||||||
files,
|
files,
|
||||||
tmpKlibDir.path,
|
tmpKlibDir,
|
||||||
emptyList(),
|
emptyList(),
|
||||||
moduleFragment,
|
moduleFragment,
|
||||||
mutableMapOf(),
|
mutableMapOf(),
|
||||||
@@ -490,7 +493,7 @@ class GenerateIrRuntime {
|
|||||||
perFile
|
perFile
|
||||||
)
|
)
|
||||||
|
|
||||||
return tmpKlibDir.path
|
return tmpKlibDir
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun doDeserializeModuleMetadata(moduleRef: KotlinLibrary): ModuleDescriptorImpl {
|
private fun doDeserializeModuleMetadata(moduleRef: KotlinLibrary): ModuleDescriptorImpl {
|
||||||
|
|||||||
+2
-2
@@ -6,6 +6,7 @@
|
|||||||
package kotlin.script.experimental.test
|
package kotlin.script.experimental.test
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.nio.file.Files
|
||||||
import kotlin.contracts.ExperimentalContracts
|
import kotlin.contracts.ExperimentalContracts
|
||||||
import kotlin.script.experimental.dependencies.*
|
import kotlin.script.experimental.dependencies.*
|
||||||
import kotlin.script.experimental.api.ResultWithDiagnostics
|
import kotlin.script.experimental.api.ResultWithDiagnostics
|
||||||
@@ -17,8 +18,7 @@ import kotlin.script.experimental.dependencies.impl.makeResolveFailureResult
|
|||||||
class ResolversTest : ResolversTestBase() {
|
class ResolversTest : ResolversTestBase() {
|
||||||
|
|
||||||
private fun <T> withTempFile(body: (file: File) -> T): T {
|
private fun <T> withTempFile(body: (file: File) -> T): T {
|
||||||
createTempFile()
|
val file = Files.createTempFile(null, null).toFile()
|
||||||
val file = createTempFile()
|
|
||||||
file.deleteOnExit()
|
file.deleteOnExit()
|
||||||
try {
|
try {
|
||||||
return body(file)
|
return body(file)
|
||||||
|
|||||||
+28
-25
@@ -3,17 +3,20 @@
|
|||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@file:OptIn(ExperimentalPathApi::class)
|
||||||
|
|
||||||
package kotlin.script.experimental.jvmhost.test
|
package kotlin.script.experimental.jvmhost.test
|
||||||
|
|
||||||
import junit.framework.TestCase
|
import junit.framework.TestCase
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
|
import java.nio.file.Path
|
||||||
import java.util.jar.JarEntry
|
import java.util.jar.JarEntry
|
||||||
import java.util.jar.JarOutputStream
|
import java.util.jar.JarOutputStream
|
||||||
import java.util.jar.Manifest
|
import java.util.jar.Manifest
|
||||||
|
import kotlin.io.path.*
|
||||||
import kotlin.script.experimental.jvm.util.classPathFromTypicalResourceUrls
|
import kotlin.script.experimental.jvm.util.classPathFromTypicalResourceUrls
|
||||||
import kotlin.script.experimental.jvm.util.classpathFromClass
|
import kotlin.script.experimental.jvm.util.classpathFromClass
|
||||||
import kotlin.script.experimental.jvm.util.classpathFromClassloader
|
import kotlin.script.experimental.jvm.util.classpathFromClassloader
|
||||||
@@ -21,22 +24,22 @@ import kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContext
|
|||||||
|
|
||||||
class ClassPathTest : TestCase() {
|
class ClassPathTest : TestCase() {
|
||||||
|
|
||||||
lateinit var tempDir: File
|
lateinit var tempDir: Path
|
||||||
|
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
tempDir = createTempDir(ClassPathTest::class.simpleName!!)
|
tempDir = createTempDirectory(ClassPathTest::class.simpleName!!)
|
||||||
super.setUp()
|
super.setUp()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun tearDown() {
|
override fun tearDown() {
|
||||||
super.tearDown()
|
super.tearDown()
|
||||||
tempDir.deleteRecursively()
|
tempDir.toFile().deleteRecursively()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testExtractFromFat() {
|
fun testExtractFromFat() {
|
||||||
val collection = createTempFile("col", ".jar", directory = tempDir).apply { createCollectionJar(emulatedCollectionFiles, "BOOT-INF") }
|
val collection = createTempFile(directory = tempDir, "col", ".jar").apply { createCollectionJar(emulatedCollectionFiles, "BOOT-INF") }
|
||||||
val cl = URLClassLoader(arrayOf(collection.toURI().toURL()), null)
|
val cl = URLClassLoader(arrayOf(collection.toUri().toURL()), null)
|
||||||
val cp = classpathFromClassloader(cl, true)
|
val cp = classpathFromClassloader(cl, true)
|
||||||
Assert.assertTrue(cp != null && cp.isNotEmpty())
|
Assert.assertTrue(cp != null && cp.isNotEmpty())
|
||||||
|
|
||||||
@@ -45,40 +48,40 @@ class ClassPathTest : TestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDetectClasspathFromResources() {
|
fun testDetectClasspathFromResources() {
|
||||||
val root1 = createTempDir("root1", directory = tempDir)
|
val root1 = createTempDirectory(directory = tempDir, "root1")
|
||||||
val jar = createTempFile("jar1", ".jar", directory = tempDir).apply { createJarWithManifest() }
|
val jar = createTempFile(directory = tempDir, "jar1", ".jar").apply { createJarWithManifest() }
|
||||||
val cl = URLClassLoader(
|
val cl = URLClassLoader(
|
||||||
(emulatedClasspath.map { File(root1, it).apply { mkdirs() }.toURI().toURL() }
|
(emulatedClasspath.map { (root1 / it).apply { createDirectories() }.toUri().toURL() }
|
||||||
+ jar.toURI().toURL()).toTypedArray(),
|
+ jar.toUri().toURL()).toTypedArray(),
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
val cp = cl.classPathFromTypicalResourceUrls().toList().map { it.canonicalFile }
|
val cp = cl.classPathFromTypicalResourceUrls().toList().map { it.canonicalFile }
|
||||||
|
|
||||||
Assert.assertTrue(cp.contains(jar.canonicalFile))
|
Assert.assertTrue(cp.contains(jar.toFile().canonicalFile))
|
||||||
for (el in emulatedClasspath) {
|
for (el in emulatedClasspath) {
|
||||||
Assert.assertTrue(cp.contains(File(root1, el).canonicalFile))
|
Assert.assertTrue(cp.contains((root1 / el).toFile().canonicalFile))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testFilterClasspath() {
|
fun testFilterClasspath() {
|
||||||
val tempDir = createTempDir().canonicalFile
|
val tempDir = createTempDirectory().toRealPath()
|
||||||
try {
|
try {
|
||||||
val files = listOf(
|
val files = listOf(
|
||||||
File(tempDir, "projX/classes"),
|
(tempDir / "projX/classes"),
|
||||||
File(tempDir, "projX/test-classes"),
|
(tempDir / "projX/test-classes"),
|
||||||
File(tempDir, "projY/classes")
|
(tempDir / "projY/classes")
|
||||||
)
|
)
|
||||||
files.forEach { it.mkdirs() }
|
files.forEach { it.createDirectories() }
|
||||||
|
|
||||||
val classloader = URLClassLoader(files.map { it.toURI().toURL() }.toTypedArray(), null)
|
val classloader = URLClassLoader(files.map { it.toUri().toURL() }.toTypedArray(), null)
|
||||||
|
|
||||||
val classpath =
|
val classpath =
|
||||||
scriptCompilationClasspathFromContextOrNull("projX", classLoader = classloader)!!.map { it.toRelativeString(tempDir) }
|
scriptCompilationClasspathFromContextOrNull("projX", classLoader = classloader)!!.map { it.toPath().relativeTo(tempDir) }
|
||||||
|
|
||||||
Assert.assertEquals(files.dropLast(1).map { it.toRelativeString(tempDir) }, classpath)
|
Assert.assertEquals(files.dropLast(1).map { it.relativeTo(tempDir) }, classpath)
|
||||||
} finally {
|
} finally {
|
||||||
tempDir.deleteRecursively()
|
tempDir.toFile().deleteRecursively()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,8 +106,8 @@ private val emulatedClasspath = arrayOf(
|
|||||||
"module2/classes/java/test/"
|
"module2/classes/java/test/"
|
||||||
)
|
)
|
||||||
|
|
||||||
fun File.createCollectionJar(fileNames: Array<String>, infDirName: String) {
|
fun Path.createCollectionJar(fileNames: Array<String>, infDirName: String) {
|
||||||
FileOutputStream(this).use { fileStream ->
|
this.outputStream().use { fileStream ->
|
||||||
val jarStream = JarOutputStream(fileStream)
|
val jarStream = JarOutputStream(fileStream)
|
||||||
jarStream.putNextEntry(JarEntry("$infDirName/classes/"))
|
jarStream.putNextEntry(JarEntry("$infDirName/classes/"))
|
||||||
jarStream.putNextEntry(JarEntry("$infDirName/lib/"))
|
jarStream.putNextEntry(JarEntry("$infDirName/lib/"))
|
||||||
@@ -131,8 +134,8 @@ fun testUnpackedCollection(classpath: List<File>, fileNames: Array<String>) {
|
|||||||
jars.checkFiles(cpJars.first().parentFile.parentFile)
|
jars.checkFiles(cpJars.first().parentFile.parentFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun File.createJarWithManifest() {
|
fun Path.createJarWithManifest() {
|
||||||
FileOutputStream(this).use { fileStream ->
|
this.outputStream().use { fileStream ->
|
||||||
val jarStream = JarOutputStream(fileStream, Manifest())
|
val jarStream = JarOutputStream(fileStream, Manifest())
|
||||||
jarStream.finish()
|
jarStream.finish()
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -23,6 +23,7 @@ import org.junit.Test
|
|||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.junit.runners.Parameterized
|
import org.junit.runners.Parameterized
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import org.jetbrains.kotlin.gradle.util.createTempDir
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
private val DEFAULT_GRADLE_VERSION = GradleVersionRequired.AtLeast("5.6.4")
|
private val DEFAULT_GRADLE_VERSION = GradleVersionRequired.AtLeast("5.6.4")
|
||||||
|
|||||||
+2
-1
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.gradle
|
package org.jetbrains.kotlin.gradle
|
||||||
|
|
||||||
import org.jetbrains.kotlin.gradle.util.findFileByName
|
import org.jetbrains.kotlin.gradle.util.findFileByName
|
||||||
|
import org.jetbrains.kotlin.gradle.util.createTempDir
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
@@ -123,7 +124,7 @@ abstract class AbstractConfigurationCacheIT : BaseGradleIT() {
|
|||||||
* directory.
|
* directory.
|
||||||
*/
|
*/
|
||||||
private fun copyReportToTempDir(htmlReportFile: File): File =
|
private fun copyReportToTempDir(htmlReportFile: File): File =
|
||||||
createTempDir().let { tempDir ->
|
createTempDir("report").let { tempDir ->
|
||||||
htmlReportFile.parentFile.copyRecursively(tempDir)
|
htmlReportFile.parentFile.copyRecursively(tempDir)
|
||||||
tempDir.resolve(htmlReportFile.name)
|
tempDir.resolve(htmlReportFile.name)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -15,6 +15,7 @@ import org.junit.After
|
|||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.lang.IllegalStateException
|
import java.lang.IllegalStateException
|
||||||
|
import java.nio.file.Files
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
class BuildSessionLoggerTest {
|
class BuildSessionLoggerTest {
|
||||||
@@ -25,7 +26,7 @@ class BuildSessionLoggerTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun prepareFolder() {
|
fun prepareFolder() {
|
||||||
rootFolder = File.createTempFile("kotlin-stats", "")
|
rootFolder = Files.createTempFile("kotlin-stats", "").toFile()
|
||||||
rootFolder.delete()
|
rootFolder.delete()
|
||||||
rootFolder.mkdirs()
|
rootFolder.mkdirs()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ dependencies {
|
|||||||
testCompile(project(":kotlin-main-kts"))
|
testCompile(project(":kotlin-main-kts"))
|
||||||
testCompileOnly(project(":compiler:cli"))
|
testCompileOnly(project(":compiler:cli"))
|
||||||
testCompileOnly(project(":kotlin-scripting-jvm-host-unshaded"))
|
testCompileOnly(project(":kotlin-scripting-jvm-host-unshaded"))
|
||||||
|
testCompile(kotlinStdlib("jdk8"))
|
||||||
testCompile(commonDep("junit"))
|
testCompile(commonDep("junit"))
|
||||||
testCompile(projectTests(":kotlin-scripting-compiler")) { isTransitive = false }
|
testCompile(projectTests(":kotlin-scripting-compiler")) { isTransitive = false }
|
||||||
testRuntime(project(":kotlin-compiler-embeddable"))
|
testRuntime(project(":kotlin-compiler-embeddable"))
|
||||||
|
|||||||
+14
-10
@@ -17,6 +17,8 @@ import org.junit.Assert
|
|||||||
import org.junit.Ignore
|
import org.junit.Ignore
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.nio.file.Path
|
||||||
|
import kotlin.io.path.*
|
||||||
|
|
||||||
class MainKtsIT {
|
class MainKtsIT {
|
||||||
|
|
||||||
@@ -51,42 +53,44 @@ class MainKtsIT {
|
|||||||
runWithKotlincAndMainKts("$TEST_DATA_ROOT/context-classloader.main.kts", listOf("MainKtsConfigurator"))
|
runWithKotlincAndMainKts("$TEST_DATA_ROOT/context-classloader.main.kts", listOf("MainKtsConfigurator"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPathApi::class)
|
||||||
@Test
|
@Test
|
||||||
fun testCachedReflection() {
|
fun testCachedReflection() {
|
||||||
val cache = createTempDir("main.kts.test")
|
val cache = createTempDirectory("main.kts.test")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
runWithKotlinRunner("$TEST_DATA_ROOT/use-reflect.main.kts", listOf("false"), cacheDir = cache)
|
runWithKotlinRunner("$TEST_DATA_ROOT/use-reflect.main.kts", listOf("false"), cacheDir = cache)
|
||||||
// second run uses the cached script
|
// second run uses the cached script
|
||||||
runWithKotlinRunner("$TEST_DATA_ROOT/use-reflect.main.kts", listOf("false"), cacheDir = cache)
|
runWithKotlinRunner("$TEST_DATA_ROOT/use-reflect.main.kts", listOf("false"), cacheDir = cache)
|
||||||
} finally {
|
} finally {
|
||||||
cache.deleteRecursively()
|
cache.toFile().deleteRecursively()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPathApi::class)
|
||||||
@Test
|
@Test
|
||||||
fun testCache() {
|
fun testCache() {
|
||||||
val script = File("$TEST_DATA_ROOT/import-test.main.kts").absolutePath
|
val script = File("$TEST_DATA_ROOT/import-test.main.kts").absolutePath
|
||||||
val cache = createTempDir("main.kts.test")
|
val cache = createTempDirectory("main.kts.test")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Assert.assertTrue(cache.exists() && cache.listFiles { f: File -> f.extension == "jar" }?.isEmpty() == true)
|
Assert.assertTrue(cache.exists() && cache.listDirectoryEntries("*.jar").isEmpty())
|
||||||
runWithKotlinRunner(script, OUT_FROM_IMPORT_TEST, cacheDir = cache)
|
runWithKotlinRunner(script, OUT_FROM_IMPORT_TEST, cacheDir = cache)
|
||||||
val cacheFile = cache.listFiles { f: File -> f.extension.equals("jar", ignoreCase = true) }?.firstOrNull()
|
val cacheFile = cache.listDirectoryEntries("*.jar").firstOrNull()
|
||||||
Assert.assertTrue(cacheFile != null && cacheFile.exists())
|
Assert.assertTrue(cacheFile != null && cacheFile.exists())
|
||||||
|
|
||||||
// run generated jar with java
|
// run generated jar with java
|
||||||
val javaExecutable = File(File(System.getProperty("java.home"), "bin"), "java")
|
val javaExecutable = File(File(System.getProperty("java.home"), "bin"), "java")
|
||||||
val args = listOf(javaExecutable.absolutePath, "-jar", cacheFile!!.path)
|
val args = listOf(javaExecutable.absolutePath, "-jar", cacheFile!!.toString())
|
||||||
runAndCheckResults(
|
runAndCheckResults(
|
||||||
args, OUT_FROM_IMPORT_TEST,
|
args, OUT_FROM_IMPORT_TEST,
|
||||||
additionalEnvVars = listOf(COMPILED_SCRIPTS_CACHE_DIR_ENV_VAR to cache.absolutePath)
|
additionalEnvVars = listOf(COMPILED_SCRIPTS_CACHE_DIR_ENV_VAR to cache.toAbsolutePath().toString())
|
||||||
)
|
)
|
||||||
|
|
||||||
// this run should use the cached script
|
// this run should use the cached script
|
||||||
runWithKotlinRunner(script, OUT_FROM_IMPORT_TEST, cacheDir = cache)
|
runWithKotlinRunner(script, OUT_FROM_IMPORT_TEST, cacheDir = cache)
|
||||||
} finally {
|
} finally {
|
||||||
cache.deleteRecursively()
|
cache.toFile().deleteRecursively()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,11 +131,11 @@ fun runWithKotlinRunner(
|
|||||||
scriptPath: String,
|
scriptPath: String,
|
||||||
expectedOutPatterns: List<String> = emptyList(),
|
expectedOutPatterns: List<String> = emptyList(),
|
||||||
expectedExitCode: Int = 0,
|
expectedExitCode: Int = 0,
|
||||||
cacheDir: File? = null
|
cacheDir: Path? = null
|
||||||
) {
|
) {
|
||||||
runWithKotlinLauncherScript(
|
runWithKotlinLauncherScript(
|
||||||
"kotlin", listOf(scriptPath), expectedOutPatterns, expectedExitCode,
|
"kotlin", listOf(scriptPath), expectedOutPatterns, expectedExitCode,
|
||||||
additionalEnvVars = listOf(COMPILED_SCRIPTS_CACHE_DIR_ENV_VAR to (cacheDir?.absolutePath ?: ""))
|
additionalEnvVars = listOf(COMPILED_SCRIPTS_CACHE_DIR_ENV_VAR to (cacheDir?.toAbsolutePath()?.toString() ?: ""))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,14 +10,16 @@ import org.jetbrains.kotlin.cli.common.ExitCode
|
|||||||
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
|
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
|
||||||
import org.jetbrains.kotlin.config.Services
|
import org.jetbrains.kotlin.config.Services
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import kotlin.io.path.ExperimentalPathApi
|
||||||
|
import kotlin.io.path.createTempDirectory
|
||||||
|
|
||||||
abstract class BaseJvmAbiTest : TestCase() {
|
abstract class BaseJvmAbiTest : TestCase() {
|
||||||
private lateinit var workingDir: File
|
private lateinit var workingDir: File
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPathApi::class)
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
super.setUp()
|
super.setUp()
|
||||||
workingDir = createTempDir(javaClass.simpleName)
|
workingDir = createTempDirectory(javaClass.simpleName).toFile().apply { deleteOnExit() }
|
||||||
workingDir.deleteOnExit()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun tearDown() {
|
override fun tearDown() {
|
||||||
|
|||||||
+3
-1
@@ -21,6 +21,8 @@ import org.jetbrains.kotlin.test.KotlinTestUtils
|
|||||||
import org.jetbrains.kotlin.test.TestJdkKind
|
import org.jetbrains.kotlin.test.TestJdkKind
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.nio.file.Files
|
||||||
|
import kotlin.io.path.*
|
||||||
import kotlin.script.experimental.annotations.KotlinScript
|
import kotlin.script.experimental.annotations.KotlinScript
|
||||||
import kotlin.script.experimental.api.*
|
import kotlin.script.experimental.api.*
|
||||||
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
@@ -160,7 +162,7 @@ object CompileTimeFibonacciConfiguration : ScriptCompilationConfiguration(
|
|||||||
.mapIndexed { index, number -> "val FIB_${index + 1} = $number" }
|
.mapIndexed { index, number -> "val FIB_${index + 1} = $number" }
|
||||||
.joinToString("\n")
|
.joinToString("\n")
|
||||||
|
|
||||||
val file = createTempFile("CompileTimeFibonacci", ".fib.kts")
|
val file = Files.createTempFile("CompileTimeFibonacci", ".fib.kts").toFile()
|
||||||
.apply {
|
.apply {
|
||||||
deleteOnExit()
|
deleteOnExit()
|
||||||
writeText(sourceCode)
|
writeText(sourceCode)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ val embeddableTestRuntime by configurations.creating {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
allTestsRuntime(commonDep("junit"))
|
allTestsRuntime(commonDep("junit"))
|
||||||
|
testCompile(kotlinStdlib("jdk8"))
|
||||||
testCompile(project(":kotlin-scripting-ide-services-unshaded"))
|
testCompile(project(":kotlin-scripting-ide-services-unshaded"))
|
||||||
testCompile(project(":kotlin-scripting-compiler"))
|
testCompile(project(":kotlin-scripting-compiler"))
|
||||||
testCompile(project(":kotlin-scripting-dependencies"))
|
testCompile(project(":kotlin-scripting-dependencies"))
|
||||||
|
|||||||
+4
-2
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
|
|||||||
import org.jetbrains.kotlin.config.Services
|
import org.jetbrains.kotlin.config.Services
|
||||||
import org.jetbrains.kotlin.scripting.ide_services.test_util.*
|
import org.jetbrains.kotlin.scripting.ide_services.test_util.*
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import kotlin.io.path.*
|
||||||
import kotlin.script.experimental.api.*
|
import kotlin.script.experimental.api.*
|
||||||
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
|
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
|
||||||
import kotlin.script.experimental.jvm.jvm
|
import kotlin.script.experimental.jvm.jvm
|
||||||
@@ -318,14 +319,15 @@ class JvmIdeServicesTest : TestCase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPathApi::class)
|
||||||
companion object {
|
companion object {
|
||||||
private const val MODULE_PATH = "plugins/scripting/scripting-ide-services-test"
|
private const val MODULE_PATH = "plugins/scripting/scripting-ide-services-test"
|
||||||
private val outputJarDir = createTempDir("temp-ide-services").toPath()
|
private val outputJarDir = createTempDirectory("temp-ide-services")
|
||||||
|
|
||||||
private data class CliCompilationResult(val exitCode: ExitCode, val outputJarPath: String)
|
private data class CliCompilationResult(val exitCode: ExitCode, val outputJarPath: String)
|
||||||
|
|
||||||
private fun compileFile(inputKtFileName: String, outputJarName: String): CliCompilationResult {
|
private fun compileFile(inputKtFileName: String, outputJarName: String): CliCompilationResult {
|
||||||
val jarPath = outputJarDir.resolve(outputJarName).toAbsolutePath().toString().replace('\\', '/')
|
val jarPath = outputJarDir.resolve(outputJarName).toAbsolutePath().invariantSeparatorsPath
|
||||||
|
|
||||||
val compilerArgs = arrayOf(
|
val compilerArgs = arrayOf(
|
||||||
"$MODULE_PATH/testData/$inputKtFileName",
|
"$MODULE_PATH/testData/$inputKtFileName",
|
||||||
|
|||||||
+2
-1
@@ -33,6 +33,7 @@ import java.io.ByteArrayOutputStream
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
import java.io.PrintStream
|
import java.io.PrintStream
|
||||||
|
import java.nio.file.Files
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
|
||||||
@@ -51,7 +52,7 @@ class CompilerClientIT {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val clientAliveFile by lazy {
|
private val clientAliveFile by lazy {
|
||||||
createTempFile("client", ".alive").apply {
|
Files.createTempFile("client", ".alive").toFile().apply {
|
||||||
deleteOnExit()
|
deleteOnExit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user