Skip to content

Commit e76fce4

Browse files
committed
Add unit tests for ChromeTrace and port FileUtilsTest from Scala2
1 parent dc10c53 commit e76fce4

File tree

2 files changed

+181
-0
lines changed

2 files changed

+181
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package dotty.tools.dotc.profile
2+
3+
import java.io.*
4+
5+
import org.junit.Assert.*
6+
import org.junit.*
7+
import java.nio.file.Files
8+
import java.nio.charset.StandardCharsets
9+
import java.util.concurrent.locks.LockSupport
10+
import scala.concurrent.duration.*
11+
12+
class ChromeTraceTest:
13+
private def testTraceOutputs(generator: ChromeTrace => Unit)(checkContent: String => Unit): Unit = {
14+
val outfile = Files.createTempFile("trace-", ".json").nn
15+
val tracer = new ChromeTrace(outfile)
16+
try generator(tracer)
17+
finally tracer.close()
18+
val content = scala.io.Source.fromFile(outfile.toFile().nn).mkString
19+
checkContent(content)
20+
}
21+
22+
@Test def traceCounterEvent(): Unit = testTraceOutputs{ tracer =>
23+
tracer.traceCounterEvent("foo", "counter1", 42, processWide = true)
24+
tracer.traceCounterEvent("bar", "counter2", 21, processWide = false)
25+
}{
26+
case s"""{"traceEvents":[
27+
{"cat":"scalac","name":"foo","ph":"C","tid":"${tid1}","pid":"${pid1}","ts":${ts1},"args":{"counter1":42}}
28+
,{"cat":"scalac","name":"bar","ph":"C","tid":"${tid2}","pid":"${pid2}","ts":${ts2},"args":{"counter2":21}}
29+
]}""" =>
30+
assertEquals(tid1, tid2)
31+
assertTrue(tid1.toIntOption.isDefined)
32+
assertNotEquals(pid1, pid2)
33+
assertTrue(pid1.toIntOption.isDefined)
34+
assertEquals(s"$pid1-$tid1", pid2)
35+
assertTrue(ts1.toLong < ts2.toLong)
36+
}
37+
38+
@Test def traceDurationEvent(): Unit = testTraceOutputs{ tracer =>
39+
tracer.traceDurationEvent(name = "name1", startNanos = 1000L, durationNanos = 2500L, tid = "this-thread")
40+
tracer.traceDurationEvent(name = "name2", startNanos = 1000L, durationNanos = 5000L, tid = "this-thread", pidSuffix = "pidSuffix")
41+
}{
42+
case s"""{"traceEvents":[
43+
{"cat":"scalac","name":"name1","ph":"X","tid":"this-thread","pid":"${pid1}","ts":1,"dur":2}
44+
,{"cat":"scalac","name":"name2","ph":"X","tid":"this-thread","pid":"${pid2}","ts":1,"dur":5}
45+
]}""" =>
46+
assertTrue(pid1.toIntOption.isDefined)
47+
assertEquals(s"$pid1-pidSuffix", pid2)
48+
}
49+
50+
@Test def traceDurationEvents(): Unit = {
51+
val testStart = System.nanoTime()
52+
testTraceOutputs{ tracer =>
53+
tracer.traceDurationEventStart(cat = "test1", name = "event1")
54+
LockSupport.parkNanos(2.millis.toNanos)
55+
tracer.traceDurationEventStart(cat = "test2", name = "event2", colour = "RED", pidSuffix = "pid-suffix")
56+
LockSupport.parkNanos(4.millis.toNanos)
57+
tracer.traceDurationEventEnd(cat = "test2", name = "event2")
58+
LockSupport.parkNanos(8.millis.toNanos)
59+
tracer.traceDurationEventEnd(cat = "test1", name = "event1", colour = "RED", pidSuffix = "pid-suffix")
60+
}{
61+
case s"""{"traceEvents":[
62+
{"cat":"test1","name":"event1","ph":"B","pid":"${pid1}","tid":"${tid1}","ts":${ts1}}
63+
,{"cat":"test2","name":"event2","ph":"B","pid":"${pid2}","tid":"${tid2}","ts":${ts2},"cname":"RED"}
64+
,{"cat":"test2","name":"event2","ph":"E","pid":"${pid3}","tid":"${tid3}","ts":${ts3}}
65+
,{"cat":"test1","name":"event1","ph":"E","pid":"${pid4}","tid":"${tid4}","ts":${ts4},"cname":"RED"}
66+
]}""" =>
67+
val traceEnd = System.nanoTime()
68+
assertTrue(tid1.toIntOption.isDefined)
69+
assertEquals(pid1, pid3)
70+
assertTrue(pid1.endsWith(s"-$tid1"))
71+
assertEquals(pid2, pid4)
72+
assertTrue(pid2.endsWith("-pid-suffix"))
73+
List(tid1, tid2, tid3).foreach: tid =>
74+
assertEquals(tid4, tid)
75+
List(pid1, pid2, pid3, pid4).foreach: pid =>
76+
assertTrue(pid.takeWhile(_ != '-').toIntOption.isDefined)
77+
78+
List(ts1, ts2, ts3, ts4).map(_.toLong) match {
79+
case all @ List(ts1, ts2, ts3, ts4) =>
80+
all.foreach: ts =>
81+
// Timestamps are presented using Epoch microsecondos
82+
assertTrue(ts >= testStart / 1000)
83+
assertTrue(ts <= traceEnd / 1000)
84+
assertTrue(ts2 >= ts1 + 2.millis.toMicros)
85+
assertTrue(ts3 >= ts2 + 4.millis.toMicros)
86+
assertTrue(ts4 >= ts3 + 8.millis.toMicros)
87+
case _ => fail("unreachable")
88+
}
89+
}
90+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package dotty.tools.dotc.profile
2+
3+
import java.io.*
4+
5+
import org.junit.Assert.*
6+
import org.junit.*
7+
8+
class FileUtilsTest {
9+
10+
@Test def writeIsSame(): Unit = {
11+
val fileTest = File.createTempFile("FileUtilsTest", "t1").nn
12+
val fileExpected = File.createTempFile("FileUtilsTest", "t2").nn
13+
14+
val sTest = FileUtils.newAsyncBufferedWriter(new FileWriter(fileTest), threadsafe = false)
15+
val sExpected = new BufferedWriter(new FileWriter(fileExpected))
16+
17+
def writeBoth(s:String, asChars: Boolean) = {
18+
if (asChars) {
19+
sTest.write(s.toCharArray)
20+
sExpected.write(s.toCharArray)
21+
} else {
22+
sTest.write(s)
23+
sExpected.write(s)
24+
}
25+
}
26+
27+
for (i <- 1 to 2000) {
28+
writeBoth(s"line $i text;", asChars = true)
29+
writeBoth(s"line $i chars", asChars = false)
30+
sTest.newLine()
31+
sExpected.newLine()
32+
}
33+
sTest.close()
34+
sExpected.close()
35+
36+
assertEquals(fileExpected.length(),fileTest.length())
37+
38+
val expIn = new BufferedReader(new FileReader(fileExpected))
39+
val testIn = new BufferedReader(new FileReader(fileTest))
40+
41+
var exp = expIn.readLine()
42+
while (exp ne null) {
43+
val actual = testIn.readLine()
44+
assertEquals(exp, actual)
45+
exp = expIn.readLine()
46+
}
47+
expIn.close()
48+
testIn.close()
49+
fileTest.delete()
50+
fileExpected.delete()
51+
}
52+
53+
@Ignore
54+
@Test def showPerformance(): Unit = {
55+
//warmup
56+
for (i <- 1 to 1000) {
57+
writeIsSame()
58+
}
59+
60+
val fileTest = File.createTempFile("FileUtilsTest", "t1").nn
61+
val fileExpected = File.createTempFile("FileUtilsTest", "t2").nn
62+
63+
for (i <- 1 to 10) {
64+
val sTest = FileUtils.newAsyncBufferedWriter(fileTest.toPath.nn)
65+
val sExpected = new BufferedWriter(new FileWriter(fileExpected))
66+
67+
val t1 = System.nanoTime()
68+
List.tabulate(10000) {i =>
69+
sTest.write(s"line $i text;")
70+
sTest.newLine()
71+
}
72+
val t2 = System.nanoTime()
73+
sTest.close()
74+
val t3 = System.nanoTime()
75+
List.tabulate(10000) {i =>
76+
sExpected.write(s"line $i text;")
77+
sExpected.newLine()
78+
}
79+
val t4 = System.nanoTime()
80+
sExpected.close()
81+
82+
println(s"async took ${t2 - t1} ns")
83+
println(s"buffered took ${t4 - t3} ns")
84+
85+
fileTest.delete()
86+
fileExpected.delete()
87+
}
88+
}
89+
90+
}
91+

0 commit comments

Comments
 (0)