Skip to content

Commit ecee151

Browse files
committed
NIT Refactor existing --watch tests
1 parent aa485b4 commit ecee151

File tree

3 files changed

+137
-171
lines changed

3 files changed

+137
-171
lines changed

modules/integration/src/test/scala/scala/cli/integration/RunTestDefinitions.scala

Lines changed: 71 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ import java.io.{ByteArrayOutputStream, File}
66
import java.nio.charset.Charset
77

88
import scala.cli.integration.util.DockerServer
9-
import scala.concurrent.ExecutionContext
10-
import scala.concurrent.duration.Duration
9+
import scala.concurrent.duration.DurationInt
1110
import scala.io.Codec
1211
import scala.jdk.CollectionConverters.*
1312
import scala.util.Properties
@@ -1509,14 +1508,12 @@ abstract class RunTestDefinitions
15091508

15101509
test("watch with interactive, with multiple main classes") {
15111510
val fileName = "watch.scala"
1512-
1513-
val inputs = TestInputs(
1511+
TestInputs(
15141512
os.rel / fileName ->
15151513
"""object Run1 extends App {println("Run1 launched")}
15161514
|object Run2 extends App {println("Run2 launched")}
15171515
|""".stripMargin
1518-
)
1519-
inputs.fromRoot { root =>
1516+
).fromRoot { root =>
15201517
val confDir = root / "config"
15211518
val confFile = confDir / "test-config.json"
15221519

@@ -1527,76 +1524,66 @@ abstract class RunTestDefinitions
15271524

15281525
val configEnv = Map("SCALA_CLI_CONFIG" -> confFile.toString)
15291526

1530-
val proc = os.proc(TestUtil.cli, "run", "--watch", "--interactive", fileName)
1531-
.spawn(
1532-
cwd = root,
1533-
mergeErrIntoOut = true,
1534-
stdout = os.Pipe,
1535-
stdin = os.Pipe,
1536-
env = Map("SCALA_CLI_INTERACTIVE" -> "true") ++ configEnv
1537-
)
1538-
1539-
try
1540-
TestUtil.withThreadPool("run-watch-interactive-multi-main-class-test", 2) { pool =>
1541-
val timeout = Duration("60 seconds")
1542-
implicit val ec = ExecutionContext.fromExecutorService(pool)
1543-
1544-
def lineReaderIter = Iterator.continually {
1545-
val line = TestUtil.readLine(proc.stdout, ec, timeout)
1546-
println(s"Line read: $line")
1547-
line
1548-
}
1527+
TestUtil.withProcessWatching(
1528+
proc = os.proc(TestUtil.cli, "run", "--watch", "--interactive", fileName)
1529+
.spawn(
1530+
cwd = root,
1531+
mergeErrIntoOut = true,
1532+
stdout = os.Pipe,
1533+
stdin = os.Pipe,
1534+
env = Map("SCALA_CLI_INTERACTIVE" -> "true") ++ configEnv
1535+
),
1536+
timeout = 60.seconds
1537+
) { (proc, timeout, ec) =>
1538+
def lineReaderIter: Iterator[String] = Iterator.continually {
1539+
val line = TestUtil.readLine(proc.stdout, ec, timeout)
1540+
println(s"Line read: $line")
1541+
line
1542+
}
15491543

1550-
def checkLinesForError(lines: Seq[String]) = munit.Assertions.assert(
1551-
!lines.exists { line =>
1552-
TestUtil.removeAnsiColors(line).contains("[error]")
1553-
},
1554-
clues(lines.toSeq)
1555-
)
1544+
def checkLinesForError(lines: Seq[String]): Unit = munit.Assertions.assert(
1545+
!lines.exists { line =>
1546+
TestUtil.removeAnsiColors(line).contains("[error]")
1547+
},
1548+
clues(lines.toSeq)
1549+
)
15561550

1557-
def answerInteractivePrompt(id: Int) = {
1558-
val interactivePromptLines = lineReaderIter
1559-
.takeWhile(!_.startsWith("[1]" /* probably [1] Run2 or [1] No*/ ))
1560-
.toList
1561-
expect(interactivePromptLines.nonEmpty)
1562-
checkLinesForError(interactivePromptLines)
1563-
proc.stdin.write(s"$id\n")
1564-
proc.stdin.flush()
1565-
}
1551+
def answerInteractivePrompt(id: Int): Unit = {
1552+
val interactivePromptLines = lineReaderIter
1553+
.takeWhile(!_.startsWith("[1]" /* probably [1] Run2 or [1] No*/ ))
1554+
.toList
1555+
expect(interactivePromptLines.nonEmpty)
1556+
checkLinesForError(interactivePromptLines)
1557+
proc.stdin.write(s"$id\n")
1558+
proc.stdin.flush()
1559+
}
15661560

1567-
def analyzeRunOutput(restart: Boolean) = {
1568-
val runResultLines = lineReaderIter
1569-
.takeWhile(!_.contains("press Enter to re-run"))
1570-
.toList
1571-
expect(runResultLines.nonEmpty)
1572-
checkLinesForError(runResultLines)
1573-
if (restart)
1574-
proc.stdin.write("\n")
1575-
proc.stdin.flush()
1576-
}
1561+
def analyzeRunOutput(restart: Boolean): Unit = {
1562+
val runResultLines = lineReaderIter
1563+
.takeWhile(!_.contains("press Enter to re-run"))
1564+
.toList
1565+
expect(runResultLines.nonEmpty)
1566+
checkLinesForError(runResultLines)
1567+
if (restart)
1568+
proc.stdin.write("\n")
1569+
proc.stdin.flush()
1570+
}
15771571

1578-
// You have run the current scala-cli command with the --interactive mode turned on.
1579-
// Would you like to leave it on permanently?
1580-
answerInteractivePrompt(0)
1572+
// You have run the current scala-cli command with the --interactive mode turned on.
1573+
// Would you like to leave it on permanently?
1574+
answerInteractivePrompt(0)
15811575

1582-
// Found several main classes. Which would you like to run?
1583-
answerInteractivePrompt(0)
1584-
expect(TestUtil.readLine(proc.stdout, ec, timeout) == "Run1 launched")
1576+
// Found several main classes. Which would you like to run?
1577+
answerInteractivePrompt(0)
1578+
expect(TestUtil.readLine(proc.stdout, ec, timeout) == "Run1 launched")
15851579

1586-
analyzeRunOutput( /* restart */ true)
1580+
analyzeRunOutput( /* restart */ true)
15871581

1588-
answerInteractivePrompt(1)
1589-
expect(TestUtil.readLine(proc.stdout, ec, timeout) == "Run2 launched")
1582+
answerInteractivePrompt(1)
1583+
expect(TestUtil.readLine(proc.stdout, ec, timeout) == "Run2 launched")
15901584

1591-
analyzeRunOutput( /* restart */ false)
1592-
}
1593-
finally
1594-
if (proc.isAlive()) {
1595-
proc.destroy()
1596-
Thread.sleep(200L)
1597-
if (proc.isAlive())
1598-
proc.destroyForcibly()
1599-
}
1585+
analyzeRunOutput( /* restart */ false)
1586+
}
16001587
}
16011588
}
16021589

@@ -2360,31 +2347,22 @@ abstract class RunTestDefinitions
23602347
val inputPath = os.rel / "smth.scala"
23612348
TestInputs(inputPath -> s"""object Smth extends App { println("$expectedMessage1") }""")
23622349
.fromRoot { root =>
2363-
val proc = os.proc(TestUtil.cli, "run", ".", "--watch", extraOptions)
2364-
.spawn(cwd = root, stderr = os.Pipe)
2365-
try
2366-
TestUtil.withThreadPool("simple-watch-scala-source-test", 2) { pool =>
2367-
val timeout = Duration("90 seconds")
2368-
val ec = ExecutionContext.fromExecutorService(pool)
2369-
val output1 = TestUtil.readLine(proc.stdout, ec, timeout)
2370-
expect(output1 == expectedMessage1)
2371-
val expectedMessage2 = "World"
2372-
while (!TestUtil.readLine(proc.stderr, ec, timeout).contains("re-run"))
2373-
Thread.sleep(100L)
2374-
os.write.over(
2375-
root / inputPath,
2376-
s"""object Smth extends App { println("$expectedMessage2") }""".stripMargin
2377-
)
2378-
val output2 = TestUtil.readLine(proc.stdout, ec, timeout)
2379-
expect(output2 == expectedMessage2)
2380-
}
2381-
finally
2382-
if (proc.isAlive()) {
2383-
proc.destroy()
2384-
Thread.sleep(200L)
2385-
if (proc.isAlive())
2386-
proc.destroyForcibly()
2387-
}
2350+
TestUtil.withProcessWatching(
2351+
os.proc(TestUtil.cli, "run", ".", "--watch", extraOptions)
2352+
.spawn(cwd = root, stderr = os.Pipe)
2353+
) { (proc, timeout, ec) =>
2354+
val output1 = TestUtil.readLine(proc.stdout, ec, timeout)
2355+
expect(output1 == expectedMessage1)
2356+
val expectedMessage2 = "World"
2357+
while (!TestUtil.readLine(proc.stderr, ec, timeout).contains("re-run"))
2358+
Thread.sleep(100L)
2359+
os.write.over(
2360+
root / inputPath,
2361+
s"""object Smth extends App { println("$expectedMessage2") }""".stripMargin
2362+
)
2363+
val output2 = TestUtil.readLine(proc.stdout, ec, timeout)
2364+
expect(output2 == expectedMessage2)
2365+
}
23882366
}
23892367
}
23902368
}

modules/integration/src/test/scala/scala/cli/integration/RunTestsDefault.scala

Lines changed: 50 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ package scala.cli.integration
22

33
import com.eed3si9n.expecty.Expecty.expect
44

5-
import scala.concurrent.ExecutionContext
6-
import scala.concurrent.duration.Duration
5+
import scala.concurrent.duration.DurationInt
76
import scala.util.{Properties, Try}
87

98
class RunTestsDefault extends RunTestDefinitions with TestDefault {
@@ -84,7 +83,7 @@ class RunTestsDefault extends RunTestDefinitions with TestDefault {
8483
| def hello(name: String) = s"$hello $$name"
8584
|}
8685
|""".stripMargin
87-
val inputs = TestInputs(
86+
TestInputs(
8887
libSourcePath -> libSource("Hello"),
8988
os.rel / "app" / "TestApp.scala" ->
9089
"""//> using lib "test-org::messages:0.1.0"
@@ -97,8 +96,7 @@ class RunTestsDefault extends RunTestDefinitions with TestDefault {
9796
|def run(): Unit =
9897
| println(Messages.hello("user"))
9998
|""".stripMargin
100-
)
101-
inputs.fromRoot { root =>
99+
).fromRoot { root =>
102100
val testRepo = root / "test-repo"
103101

104102
def publishLib(): Unit =
@@ -115,90 +113,65 @@ class RunTestsDefault extends RunTestDefinitions with TestDefault {
115113

116114
publishLib()
117115

118-
val proc = os.proc(
119-
TestUtil.cli,
120-
"--power",
121-
"run",
122-
"--offline",
123-
"app",
124-
"-w",
125-
"-r",
126-
testRepo.toNIO.toUri.toASCIIString
127-
)
128-
.spawn(cwd = root)
129-
130-
try
131-
TestUtil.withThreadPool("watch-artifacts-test", 2) { pool =>
132-
val timeout = Duration("90 seconds")
133-
val ec = ExecutionContext.fromExecutorService(pool)
134-
135-
val output = TestUtil.readLine(proc.stdout, ec, timeout)
136-
expect(output == "Hello user")
137-
138-
os.write.over(root / libSourcePath, libSource("Hola"))
139-
publishLib()
140-
141-
val secondOutput = TestUtil.readLine(proc.stdout, ec, timeout)
142-
expect(secondOutput == "Hola user")
143-
}
144-
finally
145-
if (proc.isAlive()) {
146-
proc.destroy()
147-
Thread.sleep(200L)
148-
if (proc.isAlive())
149-
proc.destroyForcibly()
150-
}
116+
TestUtil.withProcessWatching(
117+
os.proc(
118+
TestUtil.cli,
119+
"--power",
120+
"run",
121+
"--offline",
122+
"app",
123+
"-w",
124+
"-r",
125+
testRepo.toNIO.toUri.toASCIIString
126+
).spawn(cwd = root)
127+
) { (proc, timeout, ec) =>
128+
val output = TestUtil.readLine(proc.stdout, ec, timeout)
129+
expect(output == "Hello user")
130+
131+
os.write.over(root / libSourcePath, libSource("Hola"))
132+
publishLib()
133+
134+
val secondOutput = TestUtil.readLine(proc.stdout, ec, timeout)
135+
expect(secondOutput == "Hola user")
136+
}
151137
}
152138
}
153139

154140
test("watch test - no infinite loop") {
155-
156141
val fileName = "watch.scala"
157-
158-
val inputs = TestInputs(
142+
TestInputs(
159143
os.rel / fileName ->
160144
"""//> using lib "org.scalameta::munit::0.7.29"
161145
|
162146
|class MyTests extends munit.FunSuite {
163147
| test("is true true") { assert(true) }
164148
|}
165149
|""".stripMargin
166-
)
167-
inputs.fromRoot { root =>
168-
val proc = os.proc(TestUtil.cli, "test", "-w", "watch.scala")
169-
.spawn(cwd = root, mergeErrIntoOut = true)
170-
171-
val watchingMsg = "Watching sources, press Ctrl+C to exit, or press Enter to re-run."
172-
val testingMsg = "MyTests:"
173-
174-
try
175-
TestUtil.withThreadPool("watch-test-test", 2) { pool =>
176-
val timeout = Duration("10 seconds")
177-
implicit val ec = ExecutionContext.fromExecutorService(pool)
178-
179-
def lineReadIter = Iterator.continually(Try(TestUtil.readLine(proc.stdout, ec, timeout)))
180-
.takeWhile(_.isSuccess)
181-
.map(_.get)
182-
183-
val beforeAppendOut = lineReadIter.toSeq
184-
expect(beforeAppendOut.count(_.contains(testingMsg)) == 1)
185-
expect(beforeAppendOut.count(_.contains(watchingMsg)) == 1)
186-
expect(beforeAppendOut.last.contains(watchingMsg))
187-
188-
os.write.append(root / fileName, "\n//comment")
189-
190-
val afterAppendOut = lineReadIter.toSeq
191-
expect(afterAppendOut.count(_.contains(testingMsg)) == 1)
192-
expect(afterAppendOut.count(_.contains(watchingMsg)) == 1)
193-
expect(afterAppendOut.last.contains(watchingMsg))
194-
}
195-
finally
196-
if (proc.isAlive()) {
197-
proc.destroy()
198-
Thread.sleep(200L)
199-
if (proc.isAlive())
200-
proc.destroyForcibly()
201-
}
150+
).fromRoot { root =>
151+
TestUtil.withProcessWatching(
152+
proc = os.proc(TestUtil.cli, "test", "-w", "watch.scala")
153+
.spawn(cwd = root, mergeErrIntoOut = true),
154+
timeout = 10.seconds
155+
) { (proc, timeout, ec) =>
156+
val watchingMsg = "Watching sources, press Ctrl+C to exit, or press Enter to re-run."
157+
val testingMsg = "MyTests:"
158+
159+
def lineReadIter = Iterator.continually(Try(TestUtil.readLine(proc.stdout, ec, timeout)))
160+
.takeWhile(_.isSuccess)
161+
.map(_.get)
162+
163+
val beforeAppendOut = lineReadIter.toSeq
164+
expect(beforeAppendOut.count(_.contains(testingMsg)) == 1)
165+
expect(beforeAppendOut.count(_.contains(watchingMsg)) == 1)
166+
expect(beforeAppendOut.last.contains(watchingMsg))
167+
168+
os.write.append(root / fileName, "\n//comment")
169+
170+
val afterAppendOut = lineReadIter.toSeq
171+
expect(afterAppendOut.count(_.contains(testingMsg)) == 1)
172+
expect(afterAppendOut.count(_.contains(watchingMsg)) == 1)
173+
expect(afterAppendOut.last.contains(watchingMsg))
174+
}
202175
}
203176
}
204177

0 commit comments

Comments
 (0)