forked from pinterest/ktlint
-
Notifications
You must be signed in to change notification settings - Fork 0
/
FileUtilsTest.kt
340 lines (300 loc) · 12.6 KB
/
FileUtilsTest.kt
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
package com.pinterest.ktlint.internal
import com.google.common.jimfs.Configuration
import com.google.common.jimfs.Jimfs
import com.pinterest.ktlint.core.initKtLintKLogger
import java.io.File
import java.nio.file.FileSystem
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import kotlin.io.path.absolutePathString
import kotlin.io.path.isDirectory
import mu.KotlinLogging
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.condition.DisabledOnOs
import org.junit.jupiter.api.condition.EnabledOnOs
import org.junit.jupiter.api.condition.OS
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.CsvSource
import org.junit.jupiter.params.provider.ValueSource
private val logger = KotlinLogging.logger {}.initKtLintKLogger()
/**
* Tests for [fileSequence] method.
*/
internal class FileUtilsTest {
private val tempFileSystem = Jimfs.newFileSystem(Configuration.forCurrentPlatform())
private val rootDir = tempFileSystem.rootDirectories.first().toString()
private val javaFileRootDirectory = "${rootDir}Root.java".normalizePath()
private val ktFileRootDirectory = "${rootDir}Root.kt".normalizePath()
private val ktsFileRootDirectory = "${rootDir}Root.kts".normalizePath()
private val javaFileInHiddenDirectory = "${rootDir}project1/.git/Ignored.java".normalizePath()
private val ktFileInHiddenDirectory = "${rootDir}project1/.git/Ignored.kt".normalizePath()
private val ktsFileInHiddenDirectory = "${rootDir}project1/.git/Ignored.kts".normalizePath()
private val javaFileInProjectRootDirectory = "${rootDir}project1/ProjectRoot.java".normalizePath()
private val ktFileInProjectRootDirectory = "${rootDir}project1/ProjectRoot.kt".normalizePath()
private val ktsFileInProjectRootDirectory = "${rootDir}project1/ProjectRoot.kts".normalizePath()
private val ktFile1InProjectSubDirectory = "${rootDir}project1/src/main/kotlin/One.kt".normalizePath()
private val ktFile2InProjectSubDirectory = "${rootDir}project1/src/main/kotlin/example/Two.kt".normalizePath()
private val ktsFileInProjectSubDirectory = "${rootDir}project1/src/scripts/Script.kts".normalizePath()
private val javaFileInProjectSubDirectory = "${rootDir}project1/src/main/java/One.java".normalizePath()
@BeforeEach
internal fun setUp() {
tempFileSystem.apply {
createFile(javaFileRootDirectory)
createFile(ktFileRootDirectory)
createFile(ktsFileRootDirectory)
createFile(javaFileInHiddenDirectory)
createFile(ktFileInHiddenDirectory)
createFile(ktsFileInHiddenDirectory)
createFile(javaFileInProjectRootDirectory)
createFile(ktFileInProjectRootDirectory)
createFile(ktsFileInProjectRootDirectory)
createFile(ktsFileInProjectSubDirectory)
createFile(ktFile1InProjectSubDirectory)
createFile(ktFile2InProjectSubDirectory)
createFile(javaFileInProjectSubDirectory)
}
}
@AfterEach
internal fun tearDown() {
tempFileSystem.close()
}
@Test
fun `Given no patterns and no workdir then find all kt and kts files in root and all its sub directories except file in hidden directories`() {
val foundFiles = getFiles()
assertThat(foundFiles)
.containsExactlyInAnyOrder(
ktFileRootDirectory,
ktsFileRootDirectory,
ktFileInProjectRootDirectory,
ktsFileInProjectRootDirectory,
ktFile1InProjectSubDirectory,
ktFile2InProjectSubDirectory,
ktsFileInProjectSubDirectory,
).doesNotContain(
javaFileInHiddenDirectory,
ktFileInHiddenDirectory,
ktsFileInHiddenDirectory,
)
}
@Test
fun `Given some patterns and no workdir then ignore all files in hidden directories`() {
val foundFiles = getFiles(
patterns = listOf(
"project1/**/*.kt",
"project1/*.kt",
),
)
assertThat(foundFiles)
.containsExactlyInAnyOrder(
ktFileInProjectRootDirectory,
ktFile1InProjectSubDirectory,
ktFile2InProjectSubDirectory,
).doesNotContain(
javaFileInHiddenDirectory,
ktFileInHiddenDirectory,
ktsFileInHiddenDirectory,
)
}
@Test
fun `Given some patterns including a negate pattern and no workdir then select all files except files in the negate pattern`() {
val foundFiles = getFiles(
patterns = listOf(
"project1/src/**/*.kt",
"!project1/src/**/example/*.kt",
),
)
assertThat(foundFiles)
.containsExactlyInAnyOrder(ktFile1InProjectSubDirectory)
.doesNotContain(ktFile2InProjectSubDirectory)
}
@Test
fun `Given a pattern and a workdir then find all files in that workdir and all its sub directories that match the pattern`() {
val foundFiles = getFiles(
patterns = listOf(
"**/main/**/*.kt",
),
rootDir = tempFileSystem.getPath("${rootDir}project1".normalizePath()),
)
assertThat(foundFiles).containsExactlyInAnyOrder(
ktFile1InProjectSubDirectory,
ktFile2InProjectSubDirectory,
)
}
@Test
fun `Given an (relative) file path from the workdir then find all files in that workdir and all its sub directories that match the pattern`() {
val foundFiles = getFiles(
patterns = listOf("src/main/kotlin/One.kt"),
rootDir = tempFileSystem.getPath("${rootDir}project1".normalizePath()),
)
assertThat(foundFiles).containsExactlyInAnyOrder(
ktFile1InProjectSubDirectory,
)
}
@Test
fun `Given an (absolute) file path and a workdir then find that absolute path and all files in the workdir and all its sub directories that match the pattern`() {
val foundFiles = getFiles(
patterns = listOf(
"src/main/kotlin/One.kt",
ktFile2InProjectSubDirectory,
),
rootDir = tempFileSystem.getPath("${rootDir}project1".normalizePath()),
)
assertThat(foundFiles).containsExactlyInAnyOrder(
ktFile1InProjectSubDirectory,
ktFile2InProjectSubDirectory,
)
}
@Test
fun `Given a glob containing an (absolute) file path and a workdir then find all files match the pattern`() {
val foundFiles = getFiles(
patterns = listOf(
"${rootDir}project1/src/**/*.kt",
),
rootDir = tempFileSystem.getPath("${rootDir}project1".normalizePath()),
)
assertThat(foundFiles).containsExactlyInAnyOrder(
ktFile1InProjectSubDirectory,
ktFile2InProjectSubDirectory,
)
}
// Jimfs does not currently support the Windows syntax for an absolute path on the current drive (e.g. "\foo\bar")
@DisabledOnOs(OS.WINDOWS)
@ParameterizedTest(name = "Pattern: {0}")
@ValueSource(
strings = [
"~/project/src/main/kotlin/One.kt",
"~/project/src/main/kotlin/*.kt",
"~/project/src/main/kotlin/",
"~/project/src/main/kotlin",
"~/project/src/main/**/*.kt",
],
)
fun `Given a non-Windows OS and a pattern that starts with a tilde then transform the globs to the user home directory`(
pattern: String,
) {
val homeDir = System.getProperty("user.home")
val filePath = "$homeDir/project/src/main/kotlin/One.kt".normalizePath()
tempFileSystem.createFile(filePath)
val foundFiles = getFiles(
patterns = listOf(pattern),
)
assertThat(foundFiles).containsExactlyInAnyOrder(filePath)
}
@Test
fun `Given a pattern containing a double star and a workdir without subdirectories then find all files in that workdir`() {
val foundFiles = getFiles(
patterns = listOf(
"**/*.kt",
),
rootDir = tempFileSystem.getPath("${rootDir}project1/src/main/kotlin/".normalizePath()),
)
assertThat(foundFiles).containsExactlyInAnyOrder(
ktFile1InProjectSubDirectory,
ktFile2InProjectSubDirectory,
)
}
@Test
fun `Given a (relative) directory path (but not a glob) from the workdir then find all files in that workdir and it subdirectories having the default kotlin extensions`() {
logger.info {
val patterns = "src/main/kotlin"
val dir = "${rootDir}project1".normalizePath()
"`Given a (relative) directory path (but not a glob) from the workdir then find all files in that workdir and it subdirectories having the default kotlin extensions`\n" +
"\tpatterns = $patterns\n" +
"\trootDir = $dir"
}
val foundFiles = getFiles(
patterns = listOf("src/main/kotlin"),
rootDir = tempFileSystem.getPath("${rootDir}project1".normalizePath()),
)
assertThat(foundFiles).containsExactlyInAnyOrder(
ktFile1InProjectSubDirectory,
ktFile2InProjectSubDirectory,
).doesNotContain(
javaFileInProjectSubDirectory,
)
}
@EnabledOnOs(OS.WINDOWS)
@Test
fun `Given the Windows OS and some globs using backslash as file separator the convert the globs to using a forward slash`() {
val foundFiles = getFiles(
patterns = listOf(
"project1\\src\\**\\*.kt",
"!project1\\src\\**\\example\\*.kt",
),
)
assertThat(foundFiles)
.containsExactlyInAnyOrder(ktFile1InProjectSubDirectory)
.doesNotContain(ktFile2InProjectSubDirectory)
}
@EnabledOnOs(OS.WINDOWS)
@Nested
inner class ExploreFileSystem {
val rootPath = Paths.get(rootDir)
@Test
fun `Is absolute path`() {
assertThat(rootPath.isAbsolute).isTrue
}
@Test
fun `Is directory`() {
assertThat(rootPath.isDirectory()).isTrue
}
@Test
fun `Has root dir name`() {
assertThat(rootPath.absolutePathString()).isEqualTo("C:\\")
}
@ParameterizedTest(name = "Path: {0}, expected result: {1}")
@CsvSource(
value = [
", C:\\",
"project1, C:\\project1",
"project1/src, C:\\project1\\src",
"project1/src/main, C:\\project1\\src\\main",
"project1/src/main/kotlin, C:\\project1\\src\\main\\kotlin",
"project1/src/main/kotlin.One.kt, C:\\project1\\src\\main\\kotlin\\One.kt",
],
)
fun `Resolve`(path: String?, expected: String) {
val actual = rootPath.resolve(Paths.get(path ?: ""))
assertThat(actual).isEqualTo(expected)
}
@ParameterizedTest(name = "Path: {0}, expected result: {1}")
@CsvSource(
value = [
", C:\\",
"project1, C:\\project1",
"project1/src, C:\\project1\\src",
"project1/src/main, C:\\project1\\src\\main",
"project1/src/main/kotlin, C:\\project1\\src\\main\\kotlin",
"project1/src/main/kotlin.One.kt, C:\\project1\\src\\main\\kotlin\\One.kt",
],
)
fun `Resolve normalized`(path: String?, expected: String) {
val actual = rootPath.resolve(Paths.get(path?.normalizePath() ?: ""))
assertThat(actual).isEqualTo(expected)
}
}
private fun String.normalizePath() = replace('/', File.separatorChar)
private fun FileSystem.createFile(it: String) {
val filePath = getPath(it.normalizePath())
val fileDir = filePath.parent
if (!Files.exists(fileDir)) Files.createDirectories(fileDir)
Files.createFile(filePath)
}
private fun getFiles(
patterns: List<String> = emptyList(),
rootDir: Path = tempFileSystem.rootDirectories.first(),
): List<String> = tempFileSystem
.fileSequence(patterns, rootDir)
.map { it.toString() }
.toList()
.also {
logger.info {
"Getting files with [patterns = $patterns] and [rootdir = $rootDir] returns [files = $it]"
}
}
}