3
3
package com.saveourtool.save.preprocessor.service
4
4
5
5
import com.saveourtool.save.core.config.TestConfig
6
+ import com.saveourtool.save.core.config.TestConfigSections
6
7
import com.saveourtool.save.core.files.ConfigDetector
7
8
import com.saveourtool.save.core.plugin.GeneralConfig
9
+ import com.saveourtool.save.core.plugin.PluginConfig
8
10
import com.saveourtool.save.core.plugin.PluginException
9
11
import com.saveourtool.save.core.utils.buildActivePlugins
10
12
import com.saveourtool.save.core.utils.processInPlace
11
13
import com.saveourtool.save.entities.TestSuite
14
+ import com.saveourtool.save.plugin.warn.WarnPluginConfig
12
15
import com.saveourtool.save.plugins.fix.FixPlugin
16
+ import com.saveourtool.save.plugins.fixandwarn.FixAndWarnPluginConfig
13
17
import com.saveourtool.save.preprocessor.utils.toHash
14
18
import com.saveourtool.save.test.TestDto
15
19
import com.saveourtool.save.test.TestsSourceSnapshotDto
@@ -18,10 +22,14 @@ import com.saveourtool.save.testsuite.TestSuiteDto
18
22
import com.saveourtool.save.utils.EmptyResponse
19
23
import com.saveourtool.save.utils.blockingToMono
20
24
import com.saveourtool.save.utils.debug
25
+ import com.saveourtool.save.utils.error
21
26
import com.saveourtool.save.utils.info
22
27
import com.saveourtool.save.utils.requireIsAbsolute
23
28
import com.saveourtool.save.utils.thenJust
24
-
29
+ import arrow.core.Either
30
+ import arrow.core.getOrElse
31
+ import arrow.core.left
32
+ import arrow.core.right
25
33
import okio.FileSystem
26
34
import okio.Path
27
35
import okio.Path.Companion.toOkioPath
@@ -35,9 +43,14 @@ import reactor.kotlin.core.publisher.toFlux
35
43
import reactor.kotlin.core.publisher.toMono
36
44
import reactor.kotlin.core.util.function.component1
37
45
import reactor.kotlin.core.util.function.component2
46
+ import java.util.regex.PatternSyntaxException
38
47
import kotlin.io.path.absolute
39
48
import kotlin.io.path.div
40
-
49
+ import kotlin.io.path.isDirectory
50
+ import kotlin.io.path.isRegularFile
51
+ import kotlin.io.path.listDirectoryEntries
52
+ import kotlin.io.path.name
53
+ import kotlin.io.path.relativeToOrNull
41
54
import java.nio.file.Path as NioPath
42
55
43
56
/* *
@@ -60,16 +73,22 @@ class TestDiscoveringService(
60
73
sourceSnapshot : TestsSourceSnapshotDto ,
61
74
): Mono <List <TestSuite >> {
62
75
log.info { " Starting to save new test suites for root test config in $repositoryPath " }
63
- return blockingToMono {
76
+ val rootTestConfigAsync = blockingToMono {
64
77
getRootTestConfig((repositoryPath / testRootPath).absolute().normalize())
65
78
}
79
+
80
+ return rootTestConfigAsync
66
81
.zipWhen { rootTestConfig ->
67
82
{
68
83
log.info { " Starting to discover test suites for root test config ${rootTestConfig.location} " }
69
- discoverAllTestSuites(
84
+ val testSuites : List < TestSuiteDto > = discoverAllTestSuites(
70
85
rootTestConfig,
71
86
sourceSnapshot,
72
87
)
88
+ testSuites.forEach { testSuite ->
89
+ log.info { " XXX " }
90
+ }
91
+ testSuites
73
92
}.toMono()
74
93
}
75
94
.flatMap { (rootTestConfig, testSuites) ->
@@ -106,28 +125,138 @@ class TestDiscoveringService(
106
125
* @throws IllegalArgumentException when provided path doesn't point to a valid config file
107
126
*/
108
127
@NonBlocking
109
- @Suppress(" UnsafeCallOnNullableType" )
128
+ @Suppress(
129
+ " UnsafeCallOnNullableType" ,
130
+ " LongMethod" ,
131
+ " MagicNumber" ,
132
+ " RedundantHigherOrderMapUsage" ,
133
+ " VARIABLE_NAME_INCORRECT" ,
134
+ " TOO_LONG_FUNCTION" ,
135
+ " WRONG_NEWLINES" ,
136
+ )
110
137
fun getAllTestSuites (
111
138
rootTestConfig : TestConfig ,
112
139
sourceSnapshot : TestsSourceSnapshotDto ,
113
- ) = rootTestConfig
114
- .getAllTestConfigs()
115
- .asSequence()
116
- .mapNotNull { it.getGeneralConfigOrNull() }
117
- .filterNot { it.suiteName == null }
118
- .filterNot { it.description == null }
119
- .map { config ->
120
- // we operate here with suite names from only those TestConfigs, that have General section with suiteName key
121
- TestSuiteDto (
122
- config.suiteName!! ,
123
- config.description,
124
- sourceSnapshot,
125
- config.language,
126
- config.tags
127
- )
140
+ ): List <TestSuiteDto > {
141
+ log.info { " XXX getAllTestSuites()" }
142
+ val t0 = System .nanoTime()
143
+ val allTestConfigs = rootTestConfig
144
+ .getAllTestConfigs()
145
+ val t1 = System .nanoTime()
146
+ @Suppress(" FLOAT_IN_ACCURATE_CALCULATIONS" )
147
+ log.info { " XXX getAllTestConfigs() took ${(t1 - t0) / 1000L / 1e3} ms" }
148
+
149
+ return allTestConfigs
150
+ .asSequence()
151
+ .map { testConfig: TestConfig -> // XXX Replace with onEach or forEach?
152
+ log.info { " XXX Test config: $testConfig " }
153
+ val pluginConfigs = testConfig.pluginConfigs
154
+ .asSequence()
155
+ .filterNot { config ->
156
+ config is GeneralConfig
157
+ }
158
+
159
+ @Suppress(" GENERIC_VARIABLE_WRONG_DECLARATION" )
160
+ val errors = mutableListOf<String >()
161
+
162
+ @Suppress(" TYPE_ALIAS" )
163
+ val resources: MutableMap <TestConfigSections , MutableList <NioPath >> = pluginConfigs.fold(mutableMapOf ()) { acc, config ->
164
+ acc.apply {
165
+ compute(config.type) { _, valueOrNull: MutableList <NioPath >? ->
166
+ val resourceNames = config.getResourceNames().getOrElse { error ->
167
+ errors + = error
168
+ emptySequence()
169
+ }
170
+
171
+ (valueOrNull ? : mutableListOf ()).apply {
172
+ addAll(resourceNames)
173
+ }
174
+ }
175
+ }
176
+ }
177
+
178
+ resources.forEach { type, resourceNames ->
179
+ log.info { " \t $type " }
180
+ resourceNames.forEach {
181
+ log.info { " \t\t $it " }
182
+ }
183
+ }
184
+ errors.forEach { error ->
185
+ log.info { " \t $error " }
186
+ }
187
+
188
+ val warnConfigs = pluginConfigs.asSequence().mapNotNull { config ->
189
+ when (config) {
190
+ is WarnPluginConfig -> config
191
+ is FixAndWarnPluginConfig -> config.warn
192
+ else -> null
193
+ }
194
+ }.toList()
195
+ log.info { " XXX Warn configs: ${warnConfigs.size} " }
196
+ warnConfigs.forEachIndexed { index, config ->
197
+ log.info { " \t $index : wildCardInDirectoryMode = ${config.wildCardInDirectoryMode} " } // XXX Should be null
198
+ }
199
+
200
+ testConfig
201
+ }
202
+ .mapNotNull { it.getGeneralConfigOrNull() }
203
+ .filterNot { it.suiteName == null }
204
+ .filterNot { it.description == null }
205
+ .map { generalConfig: GeneralConfig ->
206
+ log.info { " XXX General config: $generalConfig " }
207
+ generalConfig
208
+ }
209
+ .map { config ->
210
+ // we operate here with suite names from only those TestConfigs, that have General section with suiteName key
211
+ TestSuiteDto (
212
+ config.suiteName!! ,
213
+ config.description,
214
+ sourceSnapshot,
215
+ config.language,
216
+ config.tags
217
+ )
218
+ }
219
+ .distinct()
220
+ .toList()
221
+ }
222
+
223
+ @Suppress(" TYPE_ALIAS" , " WRONG_NEWLINES" )
224
+ private fun PluginConfig.getResourceNames (): Either <String , Sequence <NioPath >> {
225
+ val resourceNamePattern = try {
226
+ Regex (resourceNamePatternStr)
227
+ } catch (_: PatternSyntaxException ) {
228
+ return " Resource name pattern is not a valid regular expression: \" $resourceNamePatternStr \" " .left()
128
229
}
129
- .distinct()
130
- .toList()
230
+
231
+ val configLocation = configLocation.toNioPath()
232
+ if (! configLocation.isRegularFile()) {
233
+ return " Config file doesn't exist: \" $configLocation \" " .left()
234
+ }
235
+
236
+ val testDirectory = configLocation.parent
237
+ ? : return " The parent directory of the config file is null: \" $configLocation \" " .left()
238
+ if (! testDirectory.isDirectory()) {
239
+ return " Test directory doesn't exist: \" $testDirectory \" " .left()
240
+ }
241
+
242
+ return testDirectory.listDirectoryEntries().asSequence()
243
+ .filter(NioPath ::isRegularFile)
244
+ .filterNot { file ->
245
+ file.name.equals(" save.toml" , ignoreCase = true )
246
+ }
247
+ .filterNot { file ->
248
+ file.name.equals(" save.properties" , ignoreCase = true )
249
+ }
250
+ .map { file ->
251
+ file.relativeToOrNull(testDirectory)
252
+ }
253
+ .filterNotNull()
254
+ .filterNot(NioPath ::isAbsolute)
255
+ .filter { relativeFile ->
256
+ relativeFile.name.matches(resourceNamePattern)
257
+ }
258
+ .right()
259
+ }
131
260
132
261
/* *
133
262
* Discover all test suites in the project
@@ -142,7 +271,8 @@ class TestDiscoveringService(
142
271
fun discoverAllTestSuites (
143
272
rootTestConfig : TestConfig ,
144
273
sourceSnapshot : TestsSourceSnapshotDto ,
145
- ) = getAllTestSuites(rootTestConfig, sourceSnapshot)
274
+ ): List <TestSuiteDto > =
275
+ getAllTestSuites(rootTestConfig, sourceSnapshot)
146
276
147
277
private fun Path.getRelativePath (rootTestConfig : TestConfig ) = this .toFile()
148
278
.relativeTo(rootTestConfig.directory.toFile())
0 commit comments