All Downloads are FREE. Search and download functionalities are using the official Maven repository.

toolkit.utils.test-utils.33.0.0.source-code.Utils.kt Maven / Gradle / Ivy

/*
 * Copyright (C) 2017 The ORT Project Authors (see )
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * SPDX-License-Identifier: Apache-2.0
 * License-Filename: LICENSE
 */

package org.ossreviewtoolkit.utils.test

import com.fasterxml.jackson.module.kotlin.readValue

import java.io.File
import java.time.Instant

import org.ossreviewtoolkit.downloader.VersionControlSystem
import org.ossreviewtoolkit.model.AdvisorResult
import org.ossreviewtoolkit.model.AdvisorRun
import org.ossreviewtoolkit.model.ArtifactProvenance
import org.ossreviewtoolkit.model.FileList
import org.ossreviewtoolkit.model.Hash
import org.ossreviewtoolkit.model.HashAlgorithm
import org.ossreviewtoolkit.model.Identifier
import org.ossreviewtoolkit.model.KnownProvenance
import org.ossreviewtoolkit.model.OrtResult
import org.ossreviewtoolkit.model.ProvenanceResolutionResult
import org.ossreviewtoolkit.model.RemoteArtifact
import org.ossreviewtoolkit.model.RepositoryProvenance
import org.ossreviewtoolkit.model.ScanResult
import org.ossreviewtoolkit.model.ScannerRun
import org.ossreviewtoolkit.model.config.AdvisorConfiguration
import org.ossreviewtoolkit.model.mapper
import org.ossreviewtoolkit.model.utils.alignRevisions
import org.ossreviewtoolkit.model.utils.clearVcsPath
import org.ossreviewtoolkit.model.utils.toPurl
import org.ossreviewtoolkit.utils.ort.Environment
import org.ossreviewtoolkit.utils.ort.normalizeVcsUrl

val USER_DIR = File(System.getProperty("user.dir"))

private val ORT_VERSION_REGEX = Regex("(ort_version): \".*\"")
private val JAVA_VERSION_REGEX = Regex("(java_version): \".*\"")
private val ENV_VAR_REGEX = Regex("(\\s{4}variables:)\\n(?:\\s{6}.+)+")
private val ENV_TOOL_REGEX = Regex("(\\s{4}tool_versions:)\\n(?:\\s{6}.+)+")
private val START_AND_END_TIME_REGEX = Regex("((start|end)_time): \".*\"")
private val TIMESTAMP_REGEX = Regex("(timestamp): \".*\"")

/**
 * Create an [AdvisorRun] with the given [results].
 */
fun advisorRunOf(vararg results: Pair>): AdvisorRun =
    AdvisorRun(
        startTime = Instant.now(),
        endTime = Instant.now(),
        environment = Environment(),
        config = AdvisorConfiguration(),
        results = results.toMap()
    )

/**
 * Return the content of the fun test asset file located under [path] relative to the 'assets' directory as text.
 */
fun getAssetAsString(path: String): String = getAssetFile(path).readText()

/**
 * Return the absolute file for the functional test assets at the given [path].
 */
fun getAssetFile(path: String): File = File("src/funTest/assets", path).absoluteFile

/**
 * Return a string representation of the [expectedResultFile] contents that has placeholders replaced. If a
 * [definitionFile] is provided, values that can be derived from it, like the VCS revision, are also replaced.
 * Additionally, [custom] placeholders can be replaced as well.
 */
fun patchExpectedResult(
    expectedResultFile: File,
    definitionFile: File? = null,
    custom: Map = emptyMap()
): String {
    val env = Environment()

    val replacements = buildMap {
        put("", env.buildJdk)
        put("", env.javaVersion)
        put("", env.os)
        put("\"\"", env.processors.toString())
        put("\"\"", env.maxMemory.toString())

        if (definitionFile != null) {
            val projectDir = definitionFile.parentFile
            val vcsDir = VersionControlSystem.forDirectory(projectDir)!!
            val url = vcsDir.getRemoteUrl()
            val path = vcsDir.getPathToRoot(projectDir)

            put("", "$path/${definitionFile.name}")
            put("", definitionFile.absoluteFile.invariantSeparatorsPath)
            put("", url)
            put("", vcsDir.getRevision())
            put("", path)
            put("", normalizeVcsUrl(url))
        }

        putAll(custom)
    }

    return replacements.entries.fold(expectedResultFile.readText()) { text, (oldValue, newValue) ->
        text.replace(oldValue, newValue)
    }
}

/**
 * Return a patched version of the [result] string, which is assumed to represent an ORT result (but is not required to
 * do). Values that usually change between ORT runs, like timestamps, are replaced with invariant values to allow for
 * easy comparison with expected results. If [patchStartAndEndTime] is true, start and end times are also replaced.
 * Additionally, [custom] regex replacements with substitutions can be specified.
 */
fun patchActualResult(
    result: String,
    custom: Map = emptyMap(),
    patchStartAndEndTime: Boolean = false
): String {
    fun String.replaceIf(condition: Boolean, regex: Regex, transform: (MatchResult) -> CharSequence) =
        if (condition) replace(regex, transform) else this

    return custom.entries.fold(result) { text, (pattern, replacement) -> text.replace(pattern.toRegex(), replacement) }
        .replace(ORT_VERSION_REGEX) { "${it.groupValues[1]}: \"HEAD\"" }
        .replace(JAVA_VERSION_REGEX) { "${it.groupValues[1]}: \"${System.getProperty("java.version")}\"" }
        .replace(ENV_VAR_REGEX) { "${it.groupValues[1]} {}" }
        .replace(ENV_TOOL_REGEX) { "${it.groupValues[1]} {}" }
        .replace(TIMESTAMP_REGEX) { "${it.groupValues[1]}: \"${Instant.EPOCH}\"" }
        .replaceIf(patchStartAndEndTime, START_AND_END_TIME_REGEX) { "${it.groupValues[1]}: \"${Instant.EPOCH}\"" }
}

fun readOrtResult(file: String) = readOrtResult(File(file))

fun readOrtResult(file: File) = file.mapper().readValue(patchExpectedResult(file))

/**
 * Create a [ScannerRun] with the given [pkgScanResults].
 */
fun scannerRunOf(vararg pkgScanResults: Pair>): ScannerRun {
    val pkgScanResultsWithKnownProvenance = pkgScanResults.associate { (id, scanResultsForId) ->
        id to scanResultsForId.map { scanResult ->
            scanResult.takeIf { scanResult.provenance is KnownProvenance } ?: scanResult.copy(
                provenance = ArtifactProvenance(
                    sourceArtifact = RemoteArtifact(
                        url = id.toPurl(),
                        hash = Hash.NONE
                    )
                )
            )
        }
    }

    val scanResults = pkgScanResultsWithKnownProvenance.values.flatten().mapTo(mutableSetOf()) { scanResult ->
        scanResult.copy(
            provenance = (scanResult.provenance as? RepositoryProvenance)?.clearVcsPath()?.alignRevisions()
                ?: scanResult.provenance
        )
    }

    val filePathsByProvenance = scanResults.mapNotNull { scanResult ->
        val provenance = scanResult.provenance as? KnownProvenance ?: return@mapNotNull null

        val paths = buildSet {
            scanResult.summary.copyrightFindings.mapTo(this) { it.location.path }
            scanResult.summary.licenseFindings.mapTo(this) { it.location.path }
            scanResult.summary.snippetFindings.mapTo(this) { it.sourceLocation.path }
        }

        provenance to paths
    }.groupBy({ it.first }, { it.second }).mapValues { it.value.flatten().toSet() }

    val files = filePathsByProvenance.mapTo(mutableSetOf()) { (provenance, paths) ->
        FileList(
            provenance = provenance,
            files = paths.mapTo(mutableSetOf()) {
                FileList.Entry(path = it, sha1 = HashAlgorithm.SHA1.calculate(it.encodeToByteArray()))
            }
        )
    }

    val scanners = pkgScanResults.associate { (id, scanResultsForId) ->
        id to scanResultsForId.mapTo(mutableSetOf()) { it.scanner.name }
    }

    return ScannerRun.EMPTY.copy(
        provenances = pkgScanResultsWithKnownProvenance.mapTo(mutableSetOf()) { (id, scanResultsForId) ->
            val packageProvenance = scanResultsForId.firstOrNull()?.provenance as KnownProvenance

            ProvenanceResolutionResult(
                id = id,
                packageProvenance = packageProvenance,
                subRepositories = emptyMap(),
                packageProvenanceResolutionIssue = null,
                nestedProvenanceResolutionIssue = null
            )
        },
        scanResults = scanResults,
        files = files,
        scanners = scanners
    )
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy