Fixed flakiness of BuildSessionLoggerTest

This commit is contained in:
Andrey Uskov
2021-10-29 20:21:07 +03:00
committed by TeamCityServer
parent b474b570a4
commit 2fe337f58a
2 changed files with 27 additions and 16 deletions
@@ -21,7 +21,7 @@ class BuildSessionLoggerTest {
private lateinit var rootFolder: File private lateinit var rootFolder: File
private fun statFilesCount() = rootFolder.listFiles().single().listFiles().size private fun statFilesCount() = rootFolder.listFiles()?.single()?.listFiles()?.size ?: 0
@Before @Before
fun prepareFolder() { fun prepareFolder() {
@@ -56,7 +56,7 @@ class BuildSessionLoggerTest {
logger1.finishBuildSession("", null) logger1.finishBuildSession("", null)
logger2.finishBuildSession("", null) logger2.finishBuildSession("", null)
rootFolder.listFiles().first().listFiles().forEach { file -> rootFolder.listFiles()?.first()?.listFiles()?.forEach { file ->
assertTrue( assertTrue(
file.name.matches(BuildSessionLogger.STATISTICS_FILE_NAME_PATTERN.toRegex()), file.name.matches(BuildSessionLogger.STATISTICS_FILE_NAME_PATTERN.toRegex()),
"Check that file name ${file.name} matches pattern ${BuildSessionLogger.STATISTICS_FILE_NAME_PATTERN}" "Check that file name ${file.name} matches pattern ${BuildSessionLogger.STATISTICS_FILE_NAME_PATTERN}"
@@ -73,7 +73,7 @@ class BuildSessionLoggerTest {
assertEquals(1, statFilesCount()) assertEquals(1, statFilesCount())
val file2edit = rootFolder.listFiles().first().listFiles().first() val file2edit = rootFolder.listFiles()?.first()?.listFiles()?.first() ?: fail("Could not find single stat file")
logger.startBuildSession(0, 0) logger.startBuildSession(0, 0)
logger.finishBuildSession("", null) logger.finishBuildSession("", null)
@@ -97,8 +97,8 @@ class BuildSessionLoggerTest {
logger.finishBuildSession("", null) logger.finishBuildSession("", null)
assertEquals(1, statFilesCount()) assertEquals(1, statFilesCount())
val statsFolder = rootFolder.listFiles().single() val statsFolder = rootFolder.listFiles()?.single() ?: fail("${rootFolder.absolutePath} was not created")
val singleStatFile = statsFolder.listFiles().single() val singleStatFile = statsFolder.listFiles()?.single() ?: fail("stat file was not created")
for (i in 1..200) { for (i in 1..200) {
File(statsFolder, "$i").createNewFile() File(statsFolder, "$i").createNewFile()
@@ -110,24 +110,24 @@ class BuildSessionLoggerTest {
logger.finishBuildSession("", null) logger.finishBuildSession("", null)
assertTrue( assertTrue(
statsFolder.listFiles().filter { it.name == singleStatFile.name }.count() == 1, statsFolder.listFiles()?.count { it.name == singleStatFile.name } == 1,
"Could not find expected file ${singleStatFile.name}" "Could not find expected file ${singleStatFile.name}"
) )
// files not matching the pattern should not be affected // files not matching the pattern should not be affected
assertEquals( assertEquals(
200, 200,
statsFolder.listFiles().filter { !it.name.matches(BuildSessionLogger.STATISTICS_FILE_NAME_PATTERN.toRegex()) }.count(), statsFolder.listFiles()?.count { !it.name.matches(BuildSessionLogger.STATISTICS_FILE_NAME_PATTERN.toRegex()) },
"Some files which should not be affected, were removed" "Some files which should not be affected, were removed"
) )
assertEquals( assertEquals(
maxFiles, maxFiles,
statsFolder.listFiles().filter { it.name.matches(BuildSessionLogger.STATISTICS_FILE_NAME_PATTERN.toRegex()) }.count(), statsFolder.listFiles()?.count { it.name.matches(BuildSessionLogger.STATISTICS_FILE_NAME_PATTERN.toRegex()) },
"Some files which should not be affected, were removed" "Some files which should not be affected, were removed"
) )
assertEquals( assertEquals(
statsFolder.listFiles().filter { it.name.matches(BuildSessionLogger.STATISTICS_FILE_NAME_PATTERN.toRegex()) }.sorted(), statsFolder.listFiles()?.filter { it.name.matches(BuildSessionLogger.STATISTICS_FILE_NAME_PATTERN.toRegex()) }?.sorted(),
BuildSessionLogger.listProfileFiles(statsFolder) BuildSessionLogger.listProfileFiles(statsFolder)
) )
} }
@@ -142,7 +142,7 @@ class BuildSessionLoggerTest {
logger.finishBuildSession("Build", null) logger.finishBuildSession("Build", null)
assertEquals(1, statFilesCount()) assertEquals(1, statFilesCount())
val statFile = rootFolder.listFiles().single().listFiles().single() val statFile = rootFolder.listFiles()?.single()?.listFiles()?.single() ?: fail("Could not find stat file")
statFile.appendBytes("break format of the file".toByteArray()) statFile.appendBytes("break format of the file".toByteArray())
logger.startBuildSession(1, startTime) logger.startBuildSession(1, startTime)
@@ -196,7 +196,7 @@ class BuildSessionLoggerTest {
} }
logger.finishBuildSession("Build", null) logger.finishBuildSession("Build", null)
MetricsContainer.readFromFile(rootFolder.listFiles().single().listFiles().single()) { MetricsContainer.readFromFile(rootFolder.listFiles()?.single()?.listFiles()?.single() ?: fail("Could not find stat file")) {
for (metric in StringMetrics.values()) { for (metric in StringMetrics.values()) {
assertNotNull(it.getMetric(metric), "Could not find metric ${metric.name}") assertNotNull(it.getMetric(metric), "Could not find metric ${metric.name}")
} }
@@ -24,7 +24,7 @@ class BuildSessionLogger(
companion object { companion object {
const val STATISTICS_FOLDER_NAME = "kotlin-profile" const val STATISTICS_FOLDER_NAME = "kotlin-profile"
const val STATISTICS_FILE_NAME_PATTERN = "\\d{4}-\\d{2}-\\d{2}-\\d{2}-\\d{2}-\\d{2}-\\d{3}.profile" const val STATISTICS_FILE_NAME_PATTERN = "\\d{4}-\\d{2}-\\d{2}-\\d{2}-\\d{2}-\\d{2}-\\d{3}(.\\d+)?.profile"
private const val DEFAULT_MAX_PROFILE_FILES = 1_000 private const val DEFAULT_MAX_PROFILE_FILES = 1_000
private const val DEFAULT_MAX_PROFILE_FILE_SIZE = 100_000L private const val DEFAULT_MAX_PROFILE_FILE_SIZE = 100_000L
@@ -35,7 +35,9 @@ class BuildSessionLogger(
} }
} }
private val profileFileNameFormatter = DateTimeFormatter.ofPattern("YYYY-MM-dd-HH-mm-ss-SSS'.profile'") private val profileFileNameFormatter = DateTimeFormatter.ofPattern("YYYY-MM-dd-HH-mm-ss-SSS")
private val profileFileNameSuffix = ".profile"
private val statisticsFolder: File = File( private val statisticsFolder: File = File(
rootPath, rootPath,
STATISTICS_FOLDER_NAME STATISTICS_FOLDER_NAME
@@ -80,7 +82,7 @@ class BuildSessionLogger(
closeTrackingFile() closeTrackingFile()
// Get list of existing files. Try to create folder if possible, return from function if failed to create folder // Get list of existing files. Try to create folder if possible, return from function if failed to create folder
val fileCandidates = listProfileFiles(statisticsFolder) ?: if (statisticsFolder.mkdirs()) emptyList<File>() else return val fileCandidates = listProfileFiles(statisticsFolder) ?: if (statisticsFolder.mkdirs()) emptyList() else return
for ((index, file) in fileCandidates.withIndex()) { for ((index, file) in fileCandidates.withIndex()) {
val toDelete = if (index < fileCandidates.size - maxProfileFiles) val toDelete = if (index < fileCandidates.size - maxProfileFiles)
@@ -95,12 +97,21 @@ class BuildSessionLogger(
} }
// emergency check. What if a lot of files are locked due to some reason // emergency check. What if a lot of files are locked due to some reason
if (listProfileFiles(statisticsFolder)?.size ?: 0 > maxProfileFiles * 2) { if ((listProfileFiles(statisticsFolder)?.size ?: 0) > maxProfileFiles * 2) {
trackingFile = NullRecordLogger() trackingFile = NullRecordLogger()
return return
} }
fun newFile(): File = File(statisticsFolder, profileFileNameFormatter.format(LocalDateTime.now())) fun newFile(): File {
val timestamp = profileFileNameFormatter.format(LocalDateTime.now())
var result = File(statisticsFolder, timestamp + profileFileNameSuffix)
var suffixIndex = 0
while (result.exists()) {
result = File(statisticsFolder, "${timestamp}.${suffixIndex++}$profileFileNameSuffix")
}
return result
}
val lastFile = fileCandidates.lastOrNull() ?: newFile() val lastFile = fileCandidates.lastOrNull() ?: newFile()
trackingFile = try { trackingFile = try {