Skip to content

Commit

Permalink
Add unit tests for ChromeTrace and port FileUtilsTest from Scala2
Browse files Browse the repository at this point in the history
  • Loading branch information
WojciechMazur committed Sep 12, 2024
1 parent 11a0f24 commit 75c07dc
Show file tree
Hide file tree
Showing 2 changed files with 181 additions and 0 deletions.
90 changes: 90 additions & 0 deletions compiler/test/dotty/tools/dotc/profile/ChromeTraceTest.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package dotty.tools.dotc.profile

import java.io.*

import org.junit.Assert.*
import org.junit.*
import java.nio.file.Files
import java.nio.charset.StandardCharsets
import java.util.concurrent.locks.LockSupport
import scala.concurrent.duration.*

class ChromeTraceTest:
private def testTraceOutputs(generator: ChromeTrace => Unit)(checkContent: String => Unit): Unit = {
val outfile = Files.createTempFile("trace-", ".json").nn
val tracer = new ChromeTrace(outfile)
try generator(tracer)
finally tracer.close()
val content = scala.io.Source.fromFile(outfile.toFile().nn).mkString
checkContent(content)
}

@Test def traceCounterEvent(): Unit = testTraceOutputs{ tracer =>
tracer.traceCounterEvent("foo", "counter1", 42, processWide = true)
tracer.traceCounterEvent("bar", "counter2", 21, processWide = false)
}{
case s"""{"traceEvents":[
{"cat":"scalac","name":"foo","ph":"C","tid":"${tid1}","pid":"${pid1}","ts":${ts1},"args":{"counter1":42}}
,{"cat":"scalac","name":"bar","ph":"C","tid":"${tid2}","pid":"${pid2}","ts":${ts2},"args":{"counter2":21}}
]}""" =>
assertEquals(tid1, tid2)
assertTrue(tid1.toIntOption.isDefined)
assertNotEquals(pid1, pid2)
assertTrue(pid1.toIntOption.isDefined)
assertEquals(s"$pid1-$tid1", pid2)
assertTrue(ts1.toLong < ts2.toLong)
}

@Test def traceDurationEvent(): Unit = testTraceOutputs{ tracer =>
tracer.traceDurationEvent(name = "name1", startNanos = 1000L, durationNanos = 2500L, tid = "this-thread")
tracer.traceDurationEvent(name = "name2", startNanos = 1000L, durationNanos = 5000L, tid = "this-thread", pidSuffix = "pidSuffix")
}{
case s"""{"traceEvents":[
{"cat":"scalac","name":"name1","ph":"X","tid":"this-thread","pid":"${pid1}","ts":1,"dur":2}
,{"cat":"scalac","name":"name2","ph":"X","tid":"this-thread","pid":"${pid2}","ts":1,"dur":5}
]}""" =>
assertTrue(pid1.toIntOption.isDefined)
assertEquals(s"$pid1-pidSuffix", pid2)
}

@Test def traceDurationEvents(): Unit = {
val testStart = System.nanoTime()
testTraceOutputs{ tracer =>
tracer.traceDurationEventStart(cat = "test1", name = "event1")
LockSupport.parkNanos(2.millis.toNanos)
tracer.traceDurationEventStart(cat = "test2", name = "event2", colour = "RED", pidSuffix = "pid-suffix")
LockSupport.parkNanos(4.millis.toNanos)
tracer.traceDurationEventEnd(cat = "test2", name = "event2")
LockSupport.parkNanos(8.millis.toNanos)
tracer.traceDurationEventEnd(cat = "test1", name = "event1", colour = "RED", pidSuffix = "pid-suffix")
}{
case s"""{"traceEvents":[
{"cat":"test1","name":"event1","ph":"B","pid":"${pid1}","tid":"${tid1}","ts":${ts1}}
,{"cat":"test2","name":"event2","ph":"B","pid":"${pid2}","tid":"${tid2}","ts":${ts2},"cname":"RED"}
,{"cat":"test2","name":"event2","ph":"E","pid":"${pid3}","tid":"${tid3}","ts":${ts3}}
,{"cat":"test1","name":"event1","ph":"E","pid":"${pid4}","tid":"${tid4}","ts":${ts4},"cname":"RED"}
]}""" =>
val traceEnd = System.nanoTime()
assertTrue(tid1.toIntOption.isDefined)
assertEquals(pid1, pid3)
assertTrue(pid1.endsWith(s"-$tid1"))
assertEquals(pid2, pid4)
assertTrue(pid2.endsWith("-pid-suffix"))
List(tid1, tid2, tid3).foreach: tid =>
assertEquals(tid4, tid)
List(pid1, pid2, pid3, pid4).foreach: pid =>
assertTrue(pid.takeWhile(_ != '-').toIntOption.isDefined)

List(ts1, ts2, ts3, ts4).map(_.toLong) match {
case all @ List(ts1, ts2, ts3, ts4) =>
all.foreach: ts =>
// Timestamps are presented using Epoch microsecondos
assertTrue(ts >= testStart / 1000)
assertTrue(ts <= traceEnd / 1000)
assertTrue(ts2 >= ts1 + 2.millis.toMicros)
assertTrue(ts3 >= ts2 + 4.millis.toMicros)
assertTrue(ts4 >= ts3 + 8.millis.toMicros)
case _ => fail("unreachable")
}
}
}
91 changes: 91 additions & 0 deletions compiler/test/dotty/tools/dotc/profile/FileUtilsTest.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package dotty.tools.dotc.profile

import java.io.*

import org.junit.Assert.*
import org.junit.*

class FileUtilsTest {

@Test def writeIsSame(): Unit = {
val fileTest = File.createTempFile("FileUtilsTest", "t1").nn
val fileExpected = File.createTempFile("FileUtilsTest", "t2").nn

val sTest = FileUtils.newAsyncBufferedWriter(new FileWriter(fileTest), threadsafe = false)
val sExpected = new BufferedWriter(new FileWriter(fileExpected))

def writeBoth(s:String, asChars: Boolean) = {
if (asChars) {
sTest.write(s.toCharArray)
sExpected.write(s.toCharArray)
} else {
sTest.write(s)
sExpected.write(s)
}
}

for (i <- 1 to 2000) {
writeBoth(s"line $i text;", asChars = true)
writeBoth(s"line $i chars", asChars = false)
sTest.newLine()
sExpected.newLine()
}
sTest.close()
sExpected.close()

assertEquals(fileExpected.length(),fileTest.length())

val expIn = new BufferedReader(new FileReader(fileExpected))
val testIn = new BufferedReader(new FileReader(fileTest))

var exp = expIn.readLine()
while (exp ne null) {
val actual = testIn.readLine()
assertEquals(exp, actual)
exp = expIn.readLine()
}
expIn.close()
testIn.close()
fileTest.delete()
fileExpected.delete()
}

@Ignore
@Test def showPerformance(): Unit = {
//warmup
for (i <- 1 to 1000) {
writeIsSame()
}

val fileTest = File.createTempFile("FileUtilsTest", "t1").nn
val fileExpected = File.createTempFile("FileUtilsTest", "t2").nn

for (i <- 1 to 10) {
val sTest = FileUtils.newAsyncBufferedWriter(fileTest.toPath.nn)
val sExpected = new BufferedWriter(new FileWriter(fileExpected))

val t1 = System.nanoTime()
List.tabulate(10000) {i =>
sTest.write(s"line $i text;")
sTest.newLine()
}
val t2 = System.nanoTime()
sTest.close()
val t3 = System.nanoTime()
List.tabulate(10000) {i =>
sExpected.write(s"line $i text;")
sExpected.newLine()
}
val t4 = System.nanoTime()
sExpected.close()

println(s"async took ${t2 - t1} ns")
println(s"buffered took ${t4 - t3} ns")

fileTest.delete()
fileExpected.delete()
}
}

}

0 comments on commit 75c07dc

Please sign in to comment.