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