<commit_before>package org.jetbrains.kotlin.jupyter.test

import jupyter.kotlin.JavaRuntime
import jupyter.kotlin.KotlinKernelVersion.Companion.toMaybeUnspecifiedString
import jupyter.kotlin.MimeTypedResult
import jupyter.kotlin.receivers.ConstReceiver
import kotlinx.coroutines.runBlocking
import org.jetbrains.kotlin.jupyter.GitHubRepoName
import org.jetbrains.kotlin.jupyter.GitHubRepoOwner
import org.jetbrains.kotlin.jupyter.LibrariesDir
import org.jetbrains.kotlin.jupyter.OutputConfig
import org.jetbrains.kotlin.jupyter.ReplCompilerException
import org.jetbrains.kotlin.jupyter.ReplEvalRuntimeException
import org.jetbrains.kotlin.jupyter.ReplForJupyterImpl
import org.jetbrains.kotlin.jupyter.ResolverConfig
import org.jetbrains.kotlin.jupyter.defaultRepositories
import org.jetbrains.kotlin.jupyter.defaultRuntimeProperties
import org.jetbrains.kotlin.jupyter.generateDiagnostic
import org.jetbrains.kotlin.jupyter.generateDiagnosticFromAbsolute
import org.jetbrains.kotlin.jupyter.libraries.LibraryFactory
import org.jetbrains.kotlin.jupyter.libraries.LibraryResolutionInfo
import org.jetbrains.kotlin.jupyter.libraries.LibraryResolver
import org.jetbrains.kotlin.jupyter.repl.CompletionResult
import org.jetbrains.kotlin.jupyter.repl.ListErrorsResult
import org.jetbrains.kotlin.jupyter.withPath
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.api.parallel.Execution
import org.junit.jupiter.api.parallel.ExecutionMode
import java.io.File
import kotlin.script.experimental.api.SourceCode
import kotlin.test.assertEquals
import kotlin.test.assertFails
import kotlin.test.assertNotNull
import kotlin.test.assertNull
import kotlin.test.fail

abstract class AbstractReplTest {
    protected fun String.convertCRLFtoLF(): String {
        return replace("\r\n", "\n")
    }

    companion object {
        @JvmStatic
        protected val libraryFactory = LibraryFactory.EMPTY

        @JvmStatic
        protected val homeDir = File("")
    }
}

class ReplTest : AbstractReplTest() {
    private val repl = ReplForJupyterImpl(libraryFactory, classpath)

    @Test
    fun testRepl() {
        repl.eval("val x = 3")
        val res = repl.eval("x*2")
        assertEquals(6, res.resultValue)
    }

    @Test
    fun testPropertiesGeneration() {
        // Note, this test should actually fail with ReplEvalRuntimeException, but 'cause of eval/compile
        // histories are out of sync, it fails with another exception. This test shows the wrong behavior and
        // should be fixed after fixing https://youtrack.jetbrains.com/issue/KT-36397

        // In fact, this shouldn't compile, but because of bug in compiler it fails in runtime
        assertThrows<ReplEvalRuntimeException> {
            repl.eval(
                """
                fun stack(vararg tup: Int): Int = tup.sum()
                val X = 1
                val x = stack(1, X)
                """.trimIndent()
            )

            print("")
        }
    }

    @Test
    fun testError() {
        try {
            repl.eval(
                """
                val foobar = 78
                val foobaz = "dsdsda"
                val ddd = ppp
                val ooo = foobar
                """.trimIndent()
            )
        } catch (ex: ReplCompilerException) {
            val diag = ex.firstDiagnostics
            val location = diag?.location ?: fail("Location should not be null")
            val message = ex.message

            val expectedLocation = SourceCode.Location(SourceCode.Position(3, 11), SourceCode.Position(3, 14))
            val expectedMessage = "Line_0.jupyter.kts (3:11 - 14) Unresolved reference: ppp"

            assertEquals(expectedLocation, location)
            assertEquals(expectedMessage, message)

            return
        }

        fail("Test should fail with ReplCompilerException")
    }

    @Test
    fun testReplWithReceiver() {
        val value = 5
        val cp = classpath + File(ConstReceiver::class.java.protectionDomain.codeSource.location.toURI().path)
        val repl = ReplForJupyterImpl(libraryFactory, cp, null, scriptReceivers = listOf(ConstReceiver(value)))
        val res = repl.eval("value")
        assertEquals(value, res.resultValue)
    }

    @Test
    fun testDependsOnAnnotation() {
        repl.eval("@file:DependsOn(\"de.erichseifert.gral:gral-core:0.11\")")
    }

    @Test
    fun testDependsOnAnnotationCompletion() {
        repl.eval(
            """
            @file:Repository("https://repo1.maven.org/maven2/")
            @file:DependsOn("com.github.doyaaaaaken:kotlin-csv-jvm:0.7.3")
            """.trimIndent()
        )

        val res = runBlocking {
            var res2: CompletionResult? = null
            repl.complete("import com.github.", 18) { res2 = it }
            res2
        }
        when (res) {
            is CompletionResult.Success -> res.sortedMatches().contains("doyaaaaaken")
            else -> fail("Completion should be successful")
        }
    }

    @Test
    fun testExternalStaticFunctions() {
        val res = repl.eval(
            """
            @file:DependsOn("src/test/testData/kernelTestPackage-1.0.jar")
            import pack.*
            func()
            """.trimIndent()
        )

        assertEquals(42, res.resultValue)
    }

    @Test
    fun testScriptIsolation() {
        assertFails {
            repl.eval("org.jetbrains.kotlin.jupyter.ReplLineMagics.use")
        }
    }

    @Test
    fun testDependsOnAnnotations() {
        val res = repl.eval(
            """
            @file:DependsOn("de.erichseifert.gral:gral-core:0.11")
            @file:Repository("https://repo.spring.io/libs-release")
            @file:DependsOn("org.jetbrains.kotlinx:kotlinx-html-jvm:0.7.2")
            """.trimIndent()
        )

        assertTrue(res.newClasspath.size >= 2)

        val htmlLibPath = listOf(
            "org.jetbrains.kotlinx",
            "kotlinx-html-jvm",
            "jars",
            "kotlinx-html-jvm"
        ).joinToString(File.separator)
        assertTrue(res.newClasspath.any { htmlLibPath in it })
    }

    @Test
    fun testCompletionSimple() {
        repl.eval("val foobar = 42")
        repl.eval("var foobaz = 43")

        runBlocking {
            repl.complete("val t = foo", 11) {
                result ->
                if (result is CompletionResult.Success) {
                    assertEquals(arrayListOf("foobar", "foobaz"), result.sortedMatches())
                } else {
                    fail("Result should be success")
                }
            }
        }<commit_msg>Fix kotlinx-html repo for tests<commit_after>package org.jetbrains.kotlin.jupyter.test

import jupyter.kotlin.JavaRuntime
import jupyter.kotlin.KotlinKernelVersion.Companion.toMaybeUnspecifiedString
import jupyter.kotlin.MimeTypedResult
import jupyter.kotlin.receivers.ConstReceiver
import kotlinx.coroutines.runBlocking
import org.jetbrains.kotlin.jupyter.GitHubRepoName
import org.jetbrains.kotlin.jupyter.GitHubRepoOwner
import org.jetbrains.kotlin.jupyter.LibrariesDir
import org.jetbrains.kotlin.jupyter.OutputConfig
import org.jetbrains.kotlin.jupyter.ReplCompilerException
import org.jetbrains.kotlin.jupyter.ReplEvalRuntimeException
import org.jetbrains.kotlin.jupyter.ReplForJupyterImpl
import org.jetbrains.kotlin.jupyter.ResolverConfig
import org.jetbrains.kotlin.jupyter.defaultRepositories
import org.jetbrains.kotlin.jupyter.defaultRuntimeProperties
import org.jetbrains.kotlin.jupyter.generateDiagnostic
import org.jetbrains.kotlin.jupyter.generateDiagnosticFromAbsolute
import org.jetbrains.kotlin.jupyter.libraries.LibraryFactory
import org.jetbrains.kotlin.jupyter.libraries.LibraryResolutionInfo
import org.jetbrains.kotlin.jupyter.libraries.LibraryResolver
import org.jetbrains.kotlin.jupyter.repl.CompletionResult
import org.jetbrains.kotlin.jupyter.repl.ListErrorsResult
import org.jetbrains.kotlin.jupyter.withPath
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.api.parallel.Execution
import org.junit.jupiter.api.parallel.ExecutionMode
import java.io.File
import kotlin.script.experimental.api.SourceCode
import kotlin.test.assertEquals
import kotlin.test.assertFails
import kotlin.test.assertNotNull
import kotlin.test.assertNull
import kotlin.test.fail

abstract class AbstractReplTest {
    protected fun String.convertCRLFtoLF(): String {
        return replace("\r\n", "\n")
    }

    companion object {
        @JvmStatic
        protected val libraryFactory = LibraryFactory.EMPTY

        @JvmStatic
        protected val homeDir = File("")
    }
}

class ReplTest : AbstractReplTest() {
    private val repl = ReplForJupyterImpl(libraryFactory, classpath)

    @Test
    fun testRepl() {
        repl.eval("val x = 3")
        val res = repl.eval("x*2")
        assertEquals(6, res.resultValue)
    }

    @Test
    fun testPropertiesGeneration() {
        // Note, this test should actually fail with ReplEvalRuntimeException, but 'cause of eval/compile
        // histories are out of sync, it fails with another exception. This test shows the wrong behavior and
        // should be fixed after fixing https://youtrack.jetbrains.com/issue/KT-36397

        // In fact, this shouldn't compile, but because of bug in compiler it fails in runtime
        assertThrows<ReplEvalRuntimeException> {
            repl.eval(
                """
                fun stack(vararg tup: Int): Int = tup.sum()
                val X = 1
                val x = stack(1, X)
                """.trimIndent()
            )

            print("")
        }
    }

    @Test
    fun testError() {
        try {
            repl.eval(
                """
                val foobar = 78
                val foobaz = "dsdsda"
                val ddd = ppp
                val ooo = foobar
                """.trimIndent()
            )
        } catch (ex: ReplCompilerException) {
            val diag = ex.firstDiagnostics
            val location = diag?.location ?: fail("Location should not be null")
            val message = ex.message

            val expectedLocation = SourceCode.Location(SourceCode.Position(3, 11), SourceCode.Position(3, 14))
            val expectedMessage = "Line_0.jupyter.kts (3:11 - 14) Unresolved reference: ppp"

            assertEquals(expectedLocation, location)
            assertEquals(expectedMessage, message)

            return
        }

        fail("Test should fail with ReplCompilerException")
    }

    @Test
    fun testReplWithReceiver() {
        val value = 5
        val cp = classpath + File(ConstReceiver::class.java.protectionDomain.codeSource.location.toURI().path)
        val repl = ReplForJupyterImpl(libraryFactory, cp, null, scriptReceivers = listOf(ConstReceiver(value)))
        val res = repl.eval("value")
        assertEquals(value, res.resultValue)
    }

    @Test
    fun testDependsOnAnnotation() {
        repl.eval("@file:DependsOn(\"de.erichseifert.gral:gral-core:0.11\")")
    }

    @Test
    fun testDependsOnAnnotationCompletion() {
        repl.eval(
            """
            @file:Repository("https://repo1.maven.org/maven2/")
            @file:DependsOn("com.github.doyaaaaaken:kotlin-csv-jvm:0.7.3")
            """.trimIndent()
        )

        val res = runBlocking {
            var res2: CompletionResult? = null
            repl.complete("import com.github.", 18) { res2 = it }
            res2
        }
        when (res) {
            is CompletionResult.Success -> res.sortedMatches().contains("doyaaaaaken")
            else -> fail("Completion should be successful")
        }
    }

    @Test
    fun testExternalStaticFunctions() {
        val res = repl.eval(
            """
            @file:DependsOn("src/test/testData/kernelTestPackage-1.0.jar")
            import pack.*
            func()
            """.trimIndent()
        )

        assertEquals(42, res.resultValue)
    }

    @Test
    fun testScriptIsolation() {
        assertFails {
            repl.eval("org.jetbrains.kotlin.jupyter.ReplLineMagics.use")
        }
    }

    @Test
    fun testDependsOnAnnotations() {
        val res = repl.eval(
            """
            @file:DependsOn("de.erichseifert.gral:gral-core:0.11")
            @file:Repository("https://dl.bintray.com/kotlin/kotlinx")
            @file:DependsOn("org.jetbrains.kotlinx:kotlinx-html-jvm:0.7.2")
            """.trimIndent()
        )

        assertTrue(res.newClasspath.size >= 2)

        val htmlLibPath = listOf(
            "org.jetbrains.kotlinx",
            "kotlinx-html-jvm",
            "jars",
            "kotlinx-html-jvm"
        ).joinToString(File.separator)
        assertTrue(res.newClasspath.any { htmlLibPath in it })
    }

    @Test
    fun testCompletionSimple() {
        repl.eval("val foobar = 42")
        repl.eval("var foobaz = 43")

        runBlocking {
            repl.complete("val t = foo", 11) {
                result ->
                if (result is CompletionResult.Success) {
                    assertEquals(arrayListOf("foobar", "foobaz"), result.sortedMatches())
                } else {
                    fail("Result should be success")
                }
            }
        }
{'fraction_non_alphanumeric': 0.10201793721973094, 'fraction_numerical': 0.008221225710014948, 'mean_word_length': 2.3402396405391914, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 13, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '256533', 'n_tokens_mistral': 4250, 'n_tokens_neox': 4003, 'n_words': 738}