[Native][tests] Naive implementation of glob expansion
This commit is contained in:
+117
@@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.konan.blackboxtest
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.konan.blackboxtest.support.util.expandGlob
|
||||||
|
import org.jetbrains.kotlin.konan.blackboxtest.support.util.sanitizedName
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.Assertions.assertTrue
|
||||||
|
import org.junit.jupiter.api.BeforeEach
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.api.fail
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.io.path.createTempDirectory
|
||||||
|
|
||||||
|
class GlobsExpansionTest {
|
||||||
|
private lateinit var testDir: File
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
fun setUp() {
|
||||||
|
testDir = createTempDirectory(GlobsExpansionTest::class.java.sanitizedName).toFile()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun noGlobs() {
|
||||||
|
val fileName = "file.kt"
|
||||||
|
val dirNames = listOf(null, "foo", "foo/bar", "foo/bar/baz")
|
||||||
|
|
||||||
|
dirNames.forEach { dirName ->
|
||||||
|
val fullPattern = testDir.resolveNullable(dirName).resolve(fileName)
|
||||||
|
val expansionResult = expandGlob(fullPattern)
|
||||||
|
|
||||||
|
assertEquals(1, expansionResult.size)
|
||||||
|
assertEquals(fullPattern, expansionResult.first())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun filePattern() {
|
||||||
|
val fileNames = listOf("one.kt", "two.kt", "three.kt", "four.java", "five.py")
|
||||||
|
val dirNames = listOf(null, "foo", "foo/bar", "foo/bar/baz")
|
||||||
|
val pattern = "*.kt"
|
||||||
|
|
||||||
|
dirNames.forEach { dirName ->
|
||||||
|
val dir = createDirWithFiles(dirName, fileNames)
|
||||||
|
|
||||||
|
val fullPattern = dir.resolve(pattern)
|
||||||
|
val expansionResult = expandGlob(fullPattern)
|
||||||
|
|
||||||
|
val kotlinOnyFiles = findAllKotlinFiles(dirName)
|
||||||
|
|
||||||
|
assertEquals(kotlinOnyFiles.size, expansionResult.size)
|
||||||
|
assertEquals(kotlinOnyFiles, expansionResult.toSet())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun dirPattern() {
|
||||||
|
val fileNames = listOf("one.kt", "two.kt", "three.kt", "four.java", "five.py")
|
||||||
|
val dirNames = listOf(null, "foo", "bar", "baz")
|
||||||
|
val pattern = "ba*/*.kt" // covers "bar" & "baz" dirs
|
||||||
|
|
||||||
|
dirNames.forEach { dirName -> createDirWithFiles(dirName, fileNames) }
|
||||||
|
|
||||||
|
val fullPattern = testDir.resolve(pattern)
|
||||||
|
val expansionResult = expandGlob(fullPattern)
|
||||||
|
|
||||||
|
val kotlinOnyFiles = findAllKotlinFiles("bar", "baz")
|
||||||
|
assertEquals(kotlinOnyFiles.size, expansionResult.size)
|
||||||
|
assertEquals(kotlinOnyFiles, expansionResult.toSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun doubleStarPattern() {
|
||||||
|
val fileNames = listOf("one.kt", "two.kt", "three.kt", "four.java", "five.py")
|
||||||
|
val dirNames = listOf(null, "foo", "foo/bar", "foo/bar/baz")
|
||||||
|
val pattern = "foo/**.kt" // covers "foo" and all subdirectories
|
||||||
|
|
||||||
|
dirNames.forEach { dirName -> createDirWithFiles(dirName, fileNames) }
|
||||||
|
|
||||||
|
val fullPattern = testDir.resolve(pattern)
|
||||||
|
val expansionResult = expandGlob(fullPattern)
|
||||||
|
|
||||||
|
val kotlinOnyFiles = findAllKotlinFiles("foo", "foo/bar", "foo/bar/baz")
|
||||||
|
assertEquals(kotlinOnyFiles.size, expansionResult.size)
|
||||||
|
assertEquals(kotlinOnyFiles, expansionResult.toSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createDirWithFiles(dirName: String?, fileNames: Collection<String>): File {
|
||||||
|
val dir = testDir.resolveNullable(dirName)
|
||||||
|
dir.mkdirs()
|
||||||
|
|
||||||
|
fileNames.forEach { fileName ->
|
||||||
|
dir.resolve(fileName).apply { createNewFile() }
|
||||||
|
}
|
||||||
|
|
||||||
|
return dir
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findAllKotlinFiles(vararg dirNames: String?): Set<File> = buildSet {
|
||||||
|
dirNames.forEach { dirName ->
|
||||||
|
val dir = testDir.resolveNullable(dirName)
|
||||||
|
assertTrue(dir.isDirectory) { "Directory does not exist or is not a directory: $dir ($dirName)." }
|
||||||
|
|
||||||
|
val files = dir.listFiles()?.takeIf { it.isNotEmpty() }
|
||||||
|
?: fail { "Unexpectedly empty directory: $dir ($dirName)." }
|
||||||
|
|
||||||
|
files.mapNotNullTo(this) { if (it.isFile && it.extension == "kt") it else null }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private fun File.resolveNullable(nullable: String?): File = if (nullable != null) resolve(nullable) else this
|
||||||
|
}
|
||||||
|
}
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.konan.blackboxtest.support.util
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
import java.nio.file.*
|
||||||
|
import java.nio.file.attribute.BasicFileAttributes
|
||||||
|
import kotlin.io.path.name
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Naive sub-optimal implementation of glob expansion.
|
||||||
|
*/
|
||||||
|
internal fun expandGlobTo(unexpendedPath: File, output: MutableCollection<File>) {
|
||||||
|
val normalizedUnexpandedPath = Paths.get(unexpendedPath.path).toAbsolutePath().normalize()
|
||||||
|
|
||||||
|
val paths = generateSequence(normalizedUnexpandedPath) { it.parent }.toMutableList().apply { reverse() }
|
||||||
|
for (index in 1 until paths.size) {
|
||||||
|
val path = paths[index]
|
||||||
|
|
||||||
|
val isGlob = '*' in path.name
|
||||||
|
if (isGlob) {
|
||||||
|
val basePath = paths[index - 1]
|
||||||
|
|
||||||
|
val pattern = basePath.relativize(normalizedUnexpandedPath).toString()
|
||||||
|
val matcher = FileSystems.getDefault().getPathMatcher("glob:$pattern")
|
||||||
|
|
||||||
|
Files.walkFileTree(basePath, object : SimpleFileVisitor<Path>() {
|
||||||
|
override fun visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult {
|
||||||
|
if (matcher.matches(basePath.relativize(file))) output += file.toFile()
|
||||||
|
return FileVisitResult.CONTINUE
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No globs to expand.
|
||||||
|
output += normalizedUnexpandedPath.toFile()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun expandGlob(unexpendedPath: File): Collection<File> = buildList { expandGlobTo(unexpendedPath, this) }
|
||||||
+14
-4
@@ -5,11 +5,21 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.konan.blackboxtest.support.util
|
package org.jetbrains.kotlin.konan.blackboxtest.support.util
|
||||||
|
|
||||||
internal val Class<*>.sanitizedName: String
|
internal val Class<*>.sanitizedName: String get() = sanitize(name)
|
||||||
get() = name.map { if (it.isLetterOrDigit() || it == '_') it else '_' }.joinToString("")
|
|
||||||
|
|
||||||
internal fun getSanitizedFileName(fileName: String): String =
|
internal fun getSanitizedFileName(fileName: String): String = sanitize(fileName, allowDots = true)
|
||||||
fileName.map { if (it.isLetterOrDigit() || it == '_' || it == '.') it else '_' }.joinToString("")
|
|
||||||
|
private fun sanitize(s: String, allowDots: Boolean = false) = buildString {
|
||||||
|
s.forEach { ch ->
|
||||||
|
append(
|
||||||
|
when {
|
||||||
|
ch.isLetterOrDigit() || ch == '_' -> ch
|
||||||
|
allowDots && ch == '.' -> ch
|
||||||
|
else -> '_'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal const val DEFAULT_FILE_NAME = "main.kt"
|
internal const val DEFAULT_FILE_NAME = "main.kt"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user