1+ /*
2+ * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
3+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
4+ */
5+ package org.jetbrains.kotlin.script.examples.simpleMainKts.test
6+
7+ import org.jetbrains.kotlin.script.examples.simpleMainKts.COMPILED_SCRIPTS_CACHE_DIR_PROPERTY
8+ import org.jetbrains.kotlin.script.examples.simpleMainKts.SimpleMainKtsScript
9+ import org.junit.Assert
10+ import org.junit.Test
11+ import java.io.*
12+ import java.net.URLClassLoader
13+ import kotlin.script.experimental.api.*
14+ import kotlin.script.experimental.host.toScriptSource
15+ import kotlin.script.experimental.jvm.baseClassLoader
16+ import kotlin.script.experimental.jvm.jvm
17+ import kotlin.script.experimental.jvmhost.BasicJvmScriptingHost
18+ import kotlin.script.experimental.jvmhost.createJvmCompilationConfigurationFromTemplate
19+
20+ fun evalFile (scriptFile : File , cacheDir : File ? = null): ResultWithDiagnostics <EvaluationResult > =
21+ withMainKtsCacheDir(cacheDir?.absolutePath ? : " " ) {
22+ val scriptDefinition = createJvmCompilationConfigurationFromTemplate<SimpleMainKtsScript >()
23+
24+ val evaluationEnv = ScriptEvaluationConfiguration {
25+ jvm {
26+ baseClassLoader(null )
27+ }
28+ constructorArgs(emptyArray<String >())
29+ enableScriptsInstancesSharing()
30+ }
31+
32+ BasicJvmScriptingHost ().eval(scriptFile.toScriptSource(), scriptDefinition, evaluationEnv)
33+ }
34+
35+
36+ const val TEST_DATA_ROOT = " testData"
37+
38+ class SimpleMainKtsTest {
39+
40+ @Test
41+ fun testResolveJunit () {
42+ val res = evalFile(File (" $TEST_DATA_ROOT /hello-resolve-junit.smain.kts" ))
43+ assertSucceeded(res)
44+ }
45+
46+ @Test
47+ fun testResolveJunitDynamicVer () {
48+ val errRes = evalFile(File (" $TEST_DATA_ROOT /hello-resolve-junit-dynver-error.smain.kts" ))
49+ assertFailed(" Unresolved reference: assertThrows" , errRes)
50+
51+ val res = evalFile(File (" $TEST_DATA_ROOT /hello-resolve-junit-dynver.smain.kts" ))
52+ assertSucceeded(res)
53+ }
54+
55+ @Test
56+ fun testUnresolvedJunit () {
57+ val res = evalFile(File (" $TEST_DATA_ROOT /hello-unresolved-junit.smain.kts" ))
58+ assertFailed(" Unresolved reference: junit" , res)
59+ }
60+
61+ @Test
62+ fun testResolveError () {
63+ val res = evalFile(File (" $TEST_DATA_ROOT /hello-resolve-error.smain.kts" ))
64+ assertFailed(" File 'abracadabra' not found" , res)
65+ }
66+
67+ @Test
68+ fun testResolveLog4jAndDocopt () {
69+ val res = evalFile(File (" $TEST_DATA_ROOT /resolve-log4j-and-docopt.smain.kts" ))
70+ assertSucceeded(res)
71+ }
72+
73+ private val outFromImportTest = listOf (" Hi from common" , " Hi from middle" , " sharedVar == 5" )
74+
75+ @Test
76+ fun testImport () {
77+
78+ val out = captureOut {
79+ val res = evalFile(File (" $TEST_DATA_ROOT /import-test.smain.kts" ))
80+ assertSucceeded(res)
81+ }.lines()
82+
83+ Assert .assertEquals(outFromImportTest, out )
84+ }
85+
86+ @Test
87+ fun testCompilerOptions () {
88+
89+ val out = captureOut {
90+ val res = evalFile(File (" $TEST_DATA_ROOT /compile-java6.smain.kts" ))
91+ assertSucceeded(res)
92+ assertIsJava6Bytecode(res)
93+ }.lines()
94+
95+ Assert .assertEquals(listOf (" Hi from sub" , " Hi from super" , " Hi from random" ), out )
96+ }
97+
98+ @Test
99+ fun testCache () {
100+ val script = File (" $TEST_DATA_ROOT /import-test.smain.kts" )
101+ val cache = createTempDir(" main.kts.test" )
102+
103+ try {
104+ Assert .assertTrue(cache.exists() && cache.listFiles { f: File -> f.extension == " jar" }?.isEmpty() == true )
105+ val out1 = evalSuccessWithOut(script)
106+ Assert .assertEquals(outFromImportTest, out1)
107+ Assert .assertTrue(cache.listFiles { f: File -> f.extension.equals(" jar" , ignoreCase = true ) }?.isEmpty() == true )
108+
109+ val out2 = evalSuccessWithOut(script, cache)
110+ Assert .assertEquals(outFromImportTest, out2)
111+ val casheFile = cache.listFiles { f: File -> f.extension.equals(" jar" , ignoreCase = true ) }?.firstOrNull()
112+ Assert .assertTrue(casheFile != null && casheFile.exists())
113+
114+ val out3 = captureOut {
115+ val classLoader = URLClassLoader (arrayOf(casheFile!! .toURI().toURL()), null )
116+ val clazz = classLoader.loadClass(" Import_test_smain" )
117+ val mainFn = clazz.getDeclaredMethod(" main" , Array <String >::class .java)
118+ mainFn.invoke(null , arrayOf<String >())
119+ }.lines()
120+ Assert .assertEquals(outFromImportTest, out3)
121+ } finally {
122+ cache.deleteRecursively()
123+ }
124+ }
125+
126+ @Test
127+ fun testKotlinxHtml () {
128+ val out = captureOut {
129+ val res = evalFile(File (" $TEST_DATA_ROOT /kotlinx-html.smain.kts" ))
130+ assertSucceeded(res)
131+ }.lines()
132+
133+ Assert .assertEquals(listOf (" <html>" , " <body>" , " <h1>Hello, World!</h1>" , " </body>" , " </html>" ), out )
134+ }
135+
136+ private fun assertIsJava6Bytecode (res : ResultWithDiagnostics <EvaluationResult >) {
137+ val scriptClassResource = res.valueOrThrow().returnValue.scriptClass!! .java.run {
138+ getResource(" $simpleName .class" )
139+ }
140+
141+ DataInputStream (ByteArrayInputStream (scriptClassResource.readBytes())).use { stream ->
142+ val header = stream.readInt()
143+ if (0xCAFEBABE .toInt() != header) throw IOException (" Invalid header class header: $header " )
144+ stream.readUnsignedShort() // minor
145+ val major = stream.readUnsignedShort()
146+ Assert .assertTrue(major == 50 )
147+ }
148+ }
149+
150+ private fun assertSucceeded (res : ResultWithDiagnostics <EvaluationResult >) {
151+ Assert .assertTrue(
152+ " test failed:\n ${res.reports.joinToString(" \n " ) { it.message + if (it.exception == null ) " " else " : ${it.exception} " }} " ,
153+ res is ResultWithDiagnostics .Success
154+ )
155+ }
156+
157+ private fun assertFailed (expectedError : String , res : ResultWithDiagnostics <EvaluationResult >) {
158+ Assert .assertTrue(
159+ " test failed - expecting a failure with the message \" $expectedError \" but received " +
160+ (if (res is ResultWithDiagnostics .Failure ) " failure" else " success" ) +
161+ " :\n ${res.reports.joinToString(" \n " ) { it.message + if (it.exception == null ) " " else " : ${it.exception} " }} " ,
162+ res is ResultWithDiagnostics .Failure && res.reports.any { it.message.contains(expectedError) }
163+ )
164+ }
165+
166+ private fun evalSuccessWithOut (scriptFile : File , cacheDir : File ? = null): List <String > =
167+ captureOut {
168+ val res = evalFile(scriptFile, cacheDir)
169+ assertSucceeded(res)
170+ }.lines()
171+ }
172+
173+ private fun captureOut (body : () -> Unit ): String {
174+ val outStream = ByteArrayOutputStream ()
175+ val prevOut = System .out
176+ System .setOut(PrintStream (outStream))
177+ try {
178+ body()
179+ } finally {
180+ System .out .flush()
181+ System .setOut(prevOut)
182+ }
183+ return outStream.toString().trim()
184+ }
185+
186+ private fun <T > withMainKtsCacheDir (value : String? , body : () -> T ): T {
187+ val prevCacheDir = System .getProperty(COMPILED_SCRIPTS_CACHE_DIR_PROPERTY )
188+ if (value == null ) System .clearProperty(COMPILED_SCRIPTS_CACHE_DIR_PROPERTY )
189+ else System .setProperty(COMPILED_SCRIPTS_CACHE_DIR_PROPERTY , value)
190+ try {
191+ return body()
192+ } finally {
193+ if (prevCacheDir == null ) System .clearProperty(COMPILED_SCRIPTS_CACHE_DIR_PROPERTY )
194+ else System .setProperty(COMPILED_SCRIPTS_CACHE_DIR_PROPERTY , prevCacheDir)
195+ }
196+ }
0 commit comments