@@ -15,23 +15,39 @@ abstract class ReplTestDefinitions extends ScalaCliSuite with TestScalaVersionAr
1515 actualScalaVersion.coursierVersion >= " 3.7.0-RC1" .coursierVersion
1616
1717 protected val dryRunPrefix : String = " Dry run:"
18- protected val runInReplPrefix : String = " Running in REPL:"
18+ protected val runInReplPrefix : String = " Running in Scala REPL:"
1919
2020 def runInRepl (
2121 codeToRunInRepl : String ,
22- testInputs : TestInputs = TestInputs .empty
23- )(f : os.CommandResult => Unit ): Unit = {
22+ testInputs : TestInputs = TestInputs .empty,
23+ cliOptions : Seq [String ] = Seq .empty,
24+ shouldPipeStdErr : Boolean = false ,
25+ check : Boolean = true ,
26+ env : Map [String , String ] = Map .empty
27+ )(
28+ runAfterRepl : os.CommandResult => Unit ,
29+ runBeforeReplAndGetExtraCliOpts : () => Seq [os.Shellable ] = () => Seq .empty
30+ ): Unit = {
2431 testInputs.fromRoot { root =>
25- f(
32+ val potentiallyExtraCliOpts = runBeforeReplAndGetExtraCliOpts()
33+ runAfterRepl(
2634 os.proc(
2735 TestUtil .cli,
2836 " repl" ,
37+ " ." ,
2938 " --repl-quit-after-init" ,
3039 " --repl-init-script" ,
3140 codeToRunInRepl,
32- extraOptions
41+ extraOptions,
42+ cliOptions,
43+ potentiallyExtraCliOpts
3344 )
34- .call(cwd = root)
45+ .call(
46+ cwd = root,
47+ stderr = if shouldPipeStdErr then os.Pipe else os.Inherit ,
48+ env = env,
49+ check = check
50+ )
3551 )
3652 }
3753 }
@@ -114,11 +130,154 @@ abstract class ReplTestDefinitions extends ScalaCliSuite with TestScalaVersionAr
114130 expect(output.contains(" typer" ))
115131 }
116132
117- if canRunInRepl then
133+ if canRunInRepl then {
118134 test(s " $runInReplPrefix simple " ) {
119135 val expectedMessage = " 1337"
120136 runInRepl(s """ println( $expectedMessage) """ )(r =>
121137 expect(r.out.trim() == expectedMessage)
122138 )
123139 }
140+
141+ test(s " $runInReplPrefix verify Scala version from the REPL " ) {
142+ val opts = if actualScalaVersion.startsWith(" 3" ) && ! isScala38OrNewer then
143+ Seq (" --with-compiler" )
144+ else Seq .empty
145+ runInRepl(
146+ codeToRunInRepl = s """ println( $retrieveScalaVersionCode) """ ,
147+ cliOptions = opts
148+ )(r => expect(r.out.trim() == actualScalaVersion))
149+ }
150+
151+ test(s " $runInReplPrefix test scope " ) {
152+ val message = " something something something REPL"
153+ runInRepl(
154+ codeToRunInRepl = " println(example.TestScopeExample.message)" ,
155+ testInputs = TestInputs (
156+ os.rel / " example" / " TestScopeExample.test.scala" ->
157+ s """ package example
158+ |
159+ |object TestScopeExample {
160+ | def message: String = " $message"
161+ |}
162+ | """ .stripMargin
163+ ),
164+ cliOptions = Seq (" --test" )
165+ )(r => expect(r.out.trim() == message))
166+ }
167+
168+ test(s " $runInReplPrefix ScalaPy " ) {
169+ val opts =
170+ if actualScalaVersion.startsWith(" 3" ) && ! isScala38OrNewer then Seq (" --with-compiler" )
171+ else Seq .empty
172+ runInRepl(
173+ codeToRunInRepl =
174+ s """ import me.shadaj.scalapy.py
175+ |println("Hello" + " from Scala " + $retrieveScalaVersionCode)
176+ |val sth = py.module("foo.something")
177+ |py.Dynamic.global.applyDynamicNamed("print")("" -> sth.messageStart, "" -> sth.messageEnd, "flush" -> py.Any.from(true))
178+ | """ .stripMargin,
179+ testInputs = TestInputs (
180+ os.rel / " foo" / " something.py" ->
181+ """ messageStart = 'Hello from'
182+ |messageEnd = 'ScalaPy'
183+ |""" .stripMargin
184+ ),
185+ cliOptions = Seq (" --python" , " --power" ) ++ opts,
186+ shouldPipeStdErr = true
187+ ) { res =>
188+ val output = res.out.trim().linesIterator.toVector.take(2 ).mkString(" \n " )
189+ expect(output == s """ Hello from Scala $actualScalaVersion
190+ |Hello from ScalaPy """ .stripMargin)
191+ }
192+ }
193+
194+ test(s " $runInReplPrefix ScalaPy with PYTHONSAFEPATH " ) {
195+ val opts =
196+ if actualScalaVersion.startsWith(" 3" ) && ! isScala38OrNewer then Seq (" --with-compiler" )
197+ else Seq .empty
198+ runInRepl(
199+ codeToRunInRepl =
200+ s """ import me.shadaj.scalapy.py
201+ |println("Hello" + " from Scala " + $retrieveScalaVersionCode)
202+ |val sth = py.module("foo.something")
203+ |py.Dynamic.global.applyDynamicNamed("print")("" -> sth.messageStart, "" -> sth.messageEnd, "flush" -> py.Any.from(true))
204+ | """ .stripMargin,
205+ testInputs = TestInputs (
206+ os.rel / " foo" / " something.py" ->
207+ """ messageStart = 'Hello from'
208+ |messageEnd = 'ScalaPy'
209+ |""" .stripMargin
210+ ),
211+ cliOptions = Seq (" --python" , " --power" ) ++ opts,
212+ shouldPipeStdErr = true ,
213+ // check = false, // technically should be an error, but the REPL itself doesn't return it as such.
214+ env = Map (" PYTHONSAFEPATH" -> " foo" )
215+ ) { errorRes =>
216+ // expect(errorRes.exitCode != 0) // technically should be an error, but the REPL itself doesn't return it as such.
217+ val errorOutput = TestUtil .removeAnsiColors(errorRes.err.trim() + errorRes.out.trim())
218+ expect(errorOutput.contains(" No module named 'foo'" ))
219+ }
220+ }
221+
222+ test(s " $runInReplPrefix with extra JAR " ) {
223+ runInRepl(codeToRunInRepl =
224+ """ import shapeless._; println("Here's an HList: " + (2 :: true :: "a" :: HNil))"""
225+ )(
226+ runBeforeReplAndGetExtraCliOpts = () =>
227+ val shapelessJar =
228+ os.proc(TestUtil .cs, " fetch" , " --intransitive" , " com.chuusai:shapeless_2.13:2.3.7" )
229+ .call()
230+ .out
231+ .text()
232+ .trim
233+ Seq (" --jar" , shapelessJar)
234+ ,
235+ runAfterRepl = res => expect(res.out.trim() == " Here's an HList: 2 :: true :: a :: HNil" )
236+ )
237+ }
238+
239+ test(s " $runInReplPrefix https://github.com/scala/scala3/issues/21229 " ) {
240+ runInRepl(
241+ codeToRunInRepl = " println(stuff.baz)" ,
242+ testInputs = TestInputs (
243+ os.rel / " Pprint.scala" ->
244+ """ //> using dep com.lihaoyi::pprint::0.9.0
245+ |package stuff
246+ |import scala.quoted.*
247+ |def foo = pprint(1)
248+ |inline def bar = pprint(1)
249+ |inline def baz = ${ bazImpl }
250+ |def bazImpl(using Quotes) = '{ pprint(1) }
251+ |""" .stripMargin
252+ )
253+ )(res => expect(res.out.trim().nonEmpty))
254+ }
255+
256+ test(s " $runInReplPrefix as jar " ) {
257+ val inputs = TestInputs (
258+ os.rel / " CheckCp.scala" ->
259+ """ //> using dep com.lihaoyi::os-lib:0.9.1
260+ |package checkcp
261+ |class CheckCp
262+ |object CheckCp {
263+ | def hasDir: Boolean = {
264+ | val uri: java.net.URI = classOf[checkcp.CheckCp].getProtectionDomain.getCodeSource.getLocation.toURI
265+ | os.isDir(os.Path(java.nio.file.Paths.get(uri)))
266+ | }
267+ |}
268+ |""" .stripMargin
269+ )
270+ val code = """ println("hasDir=" + checkcp.CheckCp.hasDir)"""
271+ runInRepl(codeToRunInRepl = code, testInputs = inputs) {
272+ res => expect(res.out.trim().contains(" hasDir=true" ))
273+ }
274+ runInRepl(
275+ codeToRunInRepl = code,
276+ testInputs = inputs,
277+ cliOptions = Seq (" --as-jar" , " --power" )
278+ ) {
279+ res => expect(res.out.trim().contains(" hasDir=false" ))
280+ }
281+ }
282+ }
124283}
0 commit comments