tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

BuildMetricsServiceTest.kt (8018B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 import groovy.json.JsonSlurper
      6 import org.gradle.tooling.events.task.*
      7 import org.junit.jupiter.api.Assertions.*
      8 import org.junit.jupiter.api.Test
      9 import org.junit.jupiter.api.io.TempDir
     10 import org.mockito.Mockito.*
     11 import java.io.File
     12 
     13 class BuildMetricsServiceTest {
     14    @TempDir
     15    lateinit var tempDir: File
     16 
     17    @Test
     18    fun `service records different task statuses correctly`() {
     19        val suffix = "task-status"
     20        val service = createService(tempDir, suffix)
     21 
     22        service.onFinish(createTaskEvent(":app:compileJava", upToDate = true))
     23        service.onFinish(createTaskEvent(":lib:test", fromCache = true))
     24        service.onFinish(createTaskEvent(":app:build"))
     25        service.onFinish(createTaskEvent(":app:failedTask", failed = true))
     26        service.onFinish(createTaskEvent(":app:skippedTask", skipped = true))
     27 
     28        service.close()
     29 
     30        val metricsFile = File(tempDir, "gradle/build/metrics/build-metrics-$suffix.json")
     31        assertTrue(metricsFile.exists())
     32 
     33        val metrics = JsonSlurper().parseText(metricsFile.readText()) as Map<*, *>
     34        val tasks = metrics["tasks"] as List<*>
     35        assertEquals(5, tasks.size)
     36 
     37        val taskMap = tasks.associate { task ->
     38            val t = task as Map<*, *>
     39            t["path"] to t["status"]
     40        }
     41 
     42        assertEquals("UP-TO-DATE", taskMap[":app:compileJava"])
     43        assertEquals("FROM-CACHE", taskMap[":lib:test"])
     44        assertEquals("EXECUTED", taskMap[":app:build"])
     45        assertEquals("FAILED", taskMap[":app:failedTask"])
     46        assertEquals("SKIPPED", taskMap[":app:skippedTask"])
     47    }
     48 
     49    @Test
     50    fun `service creates metrics file with correct structure`() {
     51        val suffix = "structure"
     52        val service = createService(tempDir, suffix)
     53 
     54        service.onFinish(createTaskEvent(":task1"))
     55        service.onFinish(createTaskEvent(":task2", upToDate = true))
     56 
     57        service.close()
     58 
     59        val metricsFile = File(tempDir, "gradle/build/metrics/build-metrics-$suffix.json")
     60        val metrics = JsonSlurper().parseText(metricsFile.readText()) as Map<*, *>
     61 
     62        assertNotNull(metrics["invocation"])
     63        assertNotNull(metrics["configPhase"])
     64        assertNotNull(metrics["tasks"])
     65 
     66        val tasks = metrics["tasks"] as List<*>
     67        assertEquals(2, tasks.size)
     68    }
     69 
     70    @Test
     71    fun `service uses custom file suffix`() {
     72        val suffix = "custom-suffix"
     73        val service = createService(tempDir, suffix)
     74 
     75        service.onFinish(createTaskEvent(":task1"))
     76        service.close()
     77 
     78        val metricsFile = File(tempDir, "gradle/build/metrics/build-metrics-$suffix.json")
     79        assertTrue(metricsFile.exists())
     80    }
     81 
     82    @Test
     83    fun `tasks appear in execution order`() {
     84        val suffix = "order"
     85        val service = createService(tempDir, suffix)
     86 
     87        service.onFinish(createTaskEvent(":first"))
     88        service.onFinish(createTaskEvent(":second"))
     89        service.onFinish(createTaskEvent(":third"))
     90 
     91        service.close()
     92 
     93        val metricsFile = File(tempDir, "gradle/build/metrics/build-metrics-$suffix.json")
     94        val metrics = JsonSlurper().parseText(metricsFile.readText()) as Map<*, *>
     95        val tasks = metrics["tasks"] as List<*>
     96 
     97        assertEquals(":first", (tasks[0] as Map<*, *>)["path"])
     98        assertEquals(":second", (tasks[1] as Map<*, *>)["path"])
     99        assertEquals(":third", (tasks[2] as Map<*, *>)["path"])
    100    }
    101 
    102    @Test
    103    fun `task timing fields are present in JSON`() {
    104        val suffix = "timing"
    105        val service = createService(tempDir, suffix)
    106 
    107        service.onFinish(createTaskEvent(":testTask"))
    108        service.close()
    109 
    110        val metricsFile = File(tempDir, "gradle/build/metrics/build-metrics-$suffix.json")
    111        val metrics = JsonSlurper().parseText(metricsFile.readText()) as Map<*, *>
    112        val tasks = metrics["tasks"] as List<*>
    113        val task = tasks[0] as Map<*, *>
    114 
    115        assertNotNull(task["start"])
    116        assertNotNull(task["stop"])
    117        assertNotNull(task["duration"])
    118    }
    119 
    120    @Test
    121    fun `service handles different task path formats`() {
    122        val suffix = "paths"
    123        val service = createService(tempDir, suffix)
    124 
    125        service.onFinish(createTaskEvent(":rootTask"))
    126        service.onFinish(createTaskEvent(":project:subTask"))
    127        service.onFinish(createTaskEvent(":deep:nested:project:deepTask"))
    128 
    129        service.close()
    130 
    131        val metricsFile = File(tempDir, "gradle/build/metrics/build-metrics-$suffix.json")
    132        val metrics = JsonSlurper().parseText(metricsFile.readText()) as Map<*, *>
    133        val tasks = metrics["tasks"] as List<*>
    134 
    135        val taskPaths = tasks.map { (it as Map<*, *>)["path"] }
    136        assertTrue(taskPaths.contains(":rootTask"))
    137        assertTrue(taskPaths.contains(":project:subTask"))
    138        assertTrue(taskPaths.contains(":deep:nested:project:deepTask"))
    139    }
    140 
    141    @Test
    142    fun `service creates metrics directory if it does not exist`() {
    143        val suffix = "newdir"
    144        val newTempDir = File(tempDir, "nonexistent")
    145        val service = createService(newTempDir, suffix)
    146 
    147        service.onFinish(createTaskEvent(":task"))
    148        service.close()
    149 
    150        val metricsDir = File(newTempDir, "gradle/build/metrics")
    151        assertTrue(metricsDir.exists())
    152        assertTrue(metricsDir.isDirectory)
    153 
    154        val metricsFile = File(metricsDir, "build-metrics-$suffix.json")
    155        assertTrue(metricsFile.exists())
    156    }
    157 
    158    @Suppress("UNCHECKED_CAST")
    159    private fun createService(topobjdir: File, fileSuffix: String): BuildMetricsService {
    160        val topojdirProperty = mock(org.gradle.api.provider.Property::class.java) as org.gradle.api.provider.Property<String>
    161        `when`(topojdirProperty.get()).thenReturn(topobjdir.absolutePath)
    162 
    163        val fileSuffixProperty = mock(org.gradle.api.provider.Property::class.java) as org.gradle.api.provider.Property<String>
    164        `when`(fileSuffixProperty.get()).thenReturn(fileSuffix)
    165 
    166        val parameters = object : BuildMetricsServiceParameters {
    167            override val topobjdir = topojdirProperty
    168            override val fileSuffix = fileSuffixProperty
    169        }
    170        return TestBuildMetricsService(parameters).apply {
    171            invocationStart = System.currentTimeMillis()
    172            configStart = invocationStart + 100
    173            configEnd = configStart + 200
    174        }
    175    }
    176 
    177    private fun createTaskEvent(taskPath: String, upToDate: Boolean = false, fromCache: Boolean = false, failed: Boolean = false, skipped: Boolean = false): TaskFinishEvent {
    178        val result = if (failed) mockFailedResult() else if (skipped) mockSkippedResult() else mockSuccessResult(upToDate, fromCache)
    179        val descriptor = mock(TaskOperationDescriptor::class.java).apply { `when`(getTaskPath()).thenReturn(taskPath) }
    180        return mock(TaskFinishEvent::class.java).apply { `when`(getDescriptor()).thenReturn(descriptor); `when`(getResult()).thenReturn(result) }
    181    }
    182 
    183    private fun mockSuccessResult(upToDate: Boolean, fromCache: Boolean) = mock(TaskSuccessResult::class.java).apply {
    184        `when`(getStartTime()).thenReturn(1000L); `when`(getEndTime()).thenReturn(2000L)
    185        `when`(isUpToDate()).thenReturn(upToDate); `when`(isFromCache()).thenReturn(fromCache)
    186    }
    187 
    188    private fun mockFailedResult() = mock(TaskFailureResult::class.java).apply {
    189        `when`(getStartTime()).thenReturn(1000L); `when`(getEndTime()).thenReturn(2000L)
    190    }
    191 
    192    private fun mockSkippedResult() = mock(TaskSkippedResult::class.java).apply {
    193        `when`(getStartTime()).thenReturn(1000L); `when`(getEndTime()).thenReturn(2000L)
    194    }
    195 
    196    class TestBuildMetricsService(private val testParameters: BuildMetricsServiceParameters) : BuildMetricsService(testParameters) {
    197        override fun getParameters() = testParameters
    198    }
    199 }