toolkit.utils.test-utils.33.0.0.source-code.Matchers.kt Maven / Gradle / Ivy
/*
* Copyright (C) 2022 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.github.difflib.DiffUtils
import com.github.difflib.UnifiedDiffUtils
import io.kotest.matchers.Matcher
import io.kotest.matchers.MatcherResult
import io.kotest.matchers.collections.beEmpty
import io.kotest.matchers.equalityMatcher
import io.kotest.matchers.neverNullMatcher
import java.io.File
import org.ossreviewtoolkit.downloader.VersionControlSystem
import org.ossreviewtoolkit.model.OrtResult
import org.ossreviewtoolkit.model.ProjectAnalyzerResult
/**
* A helper function to create a custom matcher that compares an [expected] collection to a collection obtained by
* [transform] using the provided [matcher].
*/
fun transformingCollectionMatcher(
expected: Collection,
matcher: (Collection) -> Matcher>,
transform: (T) -> Collection
): Matcher = neverNullMatcher { value -> matcher(expected).test(transform(value)) }
/**
* A helper function to create custom matchers that assert that the collection obtained by [transform] is empty.
*/
fun transformingCollectionEmptyMatcher(transform: (T) -> Collection): Matcher =
neverNullMatcher { value -> beEmpty().test(transform(value)) }
/**
* A matcher for comparing to expected result files, in particular serialized [ProjectAnalyzerResult]s and [OrtResult]s,
* that displays a unified diff with the given [contextSize] if the results do not match. If the Kotest system property
* named "kotest.assertions.multi-line-diff" is set to "simple", this just falls back to [equalityMatcher].
*/
fun matchExpectedResult(
expectedResultFile: File,
definitionFile: File? = null,
custom: Map = emptyMap(),
contextSize: Int = 7
): Matcher {
val expected = patchExpectedResult(expectedResultFile, definitionFile, custom)
val multiLineDiff = System.getProperty("kotest.assertions.multi-line-diff")
if (multiLineDiff != "unified") return equalityMatcher(expected)
return Matcher { actual ->
val vcsDir = VersionControlSystem.forDirectory(expectedResultFile)!!
val relativeExpectedResultFile = vcsDir.getPathToRoot(expectedResultFile)
val expectedLines = expected.lines()
val actualLines = actual.lines()
MatcherResult(
expected == actual,
{
val diff = UnifiedDiffUtils.generateUnifiedDiff(
"a/$relativeExpectedResultFile",
"b/$relativeExpectedResultFile",
expectedLines,
DiffUtils.diff(expectedLines, actualLines),
contextSize
)
"""
Expected and actual results differ. To use the actual results as the new expected results, first
copy one of the following commands to the clipboard and paste it to a terminal without running it
yet:
- `wl-paste | patch -p1` (Linux with Wayland)
- `xsel -b | patch -p1` (Linux with X)
- `cat /dev/clipboard | patch -p1` (Windows with Git Bash)
- `pbpaste | patch -p1` (macOS)
Then copy the following lines to the clipboard and run the previously pasted commands.
""".trimIndent() + diff.joinToString("\n", "\n")
},
{ "Expected and actual results should differ, but they match." }
)
}
}