aboutsummaryrefslogtreecommitdiff
path: root/plugins/base/src/test/kotlin/expect/AbstractExpectTest.kt
blob: 7f187127ee5505aecae907ca42b1e1aac760d17f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/*
 * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
 */

package expect

import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.util.concurrent.TimeUnit
import kotlin.test.assertEquals
import kotlin.test.assertTrue

abstract class AbstractExpectTest(
    val testDir: Path? = Paths.get("src/test", "resources", "expect"),
    val formats: List<String> = listOf("html")
) : BaseAbstractTest() {

    protected fun generateOutput(path: Path, outFormat: String): Path? {
        val config = dokkaConfiguration {
            format = outFormat
            sourceSets {
                sourceSet {
                    sourceRoots = listOf(path.toAbsolutePath().asString())
                }
            }
        }

        var result: Path? = null
        testFromData(config, cleanupOutput = false) {
            renderingStage = { _, context -> result = context.configuration.outputDir.toPath() }
        }
        return result
    }

    protected fun compareOutput(expected: Path, obtained: Path?, gitTimeout: Long = 500) {
        obtained?.let { path ->
            val gitCompare = ProcessBuilder(
                "git",
                "--no-pager",
                "diff",
                expected.asString(),
                path.asString()
            ).also { logger.info("git diff command: ${it.command().joinToString(" ")}") }
                .also { it.redirectErrorStream() }.start()

            assertTrue(gitCompare.waitFor(gitTimeout, TimeUnit.MILLISECONDS), "Git timed out after $gitTimeout")
            gitCompare.inputStream.bufferedReader().lines().forEach { logger.info(it) }
            assertEquals(0, gitCompare.exitValue(), "${path.fileName}: outputs don't match")
        } ?: throw AssertionError("obtained path is null")
    }

    protected fun compareOutputWithExcludes(
        expected: Path,
        obtained: Path?,
        excludes: List<String>,
        timeout: Long = 500
    ) {
        obtained?.let { _ ->
            val (res, out, err) = runDiff(expected, obtained, excludes, timeout)
            assertEquals(0, res, "Outputs differ:\nstdout - $out\n\nstderr - ${err ?: ""}")
        } ?: throw AssertionError("obtained path is null")
    }

    protected fun runDiff(exp: Path, obt: Path, excludes: List<String>, timeout: Long): ProcessResult =
        ProcessBuilder().command(
            listOf("diff", "-ru") + excludes.flatMap { listOf("-x", it) } + listOf("--", exp.asString(), obt.asString())
        ).also {
            it.redirectErrorStream()
        }.start().also { assertTrue(it.waitFor(timeout, TimeUnit.MILLISECONDS), "diff timed out") }.let {
            ProcessResult(it.exitValue(), it.inputStream.bufferResult())
        }


    protected fun testOutput(p: Path, outFormat: String) {
        val expectOut = p.resolve("out/$outFormat")
        val testOut = generateOutput(p.resolve("src"), outFormat)
            .also { logger.info("Test out: ${it?.asString()}") }

        compareOutput(expectOut.toAbsolutePath(), testOut?.toAbsolutePath())
        testOut?.deleteRecursively()
    }

    protected fun testOutputWithExcludes(
        p: Path,
        outFormat: String,
        ignores: List<String> = emptyList(),
        timeout: Long = 500
    ) {
        val expected = p.resolve("out/$outFormat")
        generateOutput(p.resolve("src"), outFormat)
            ?.let { obtained ->
                compareOutputWithExcludes(expected, obtained, ignores, timeout)

                obtained.deleteRecursively()
            } ?: throw AssertionError("Output not generated for ${p.fileName}")
    }

    protected fun generateExpect(p: Path, outFormat: String) {
        val out = p.resolve("out/$outFormat/")
        Files.createDirectories(out)

        val ret = generateOutput(p.resolve("src"), outFormat)
        Files.list(out).forEach { it.deleteRecursively() }
        ret?.let { Files.list(it).forEach { f -> f.copyRecursively(out.resolve(f.fileName)) } }
    }

}