@@ -48,7 +48,7 @@ import java.nio.file.Path
48
48
import java.nio.file.Paths
49
49
import java.util.concurrent.TimeUnit
50
50
import kotlin.io.path.pathString
51
- import org.utbot.framework.plugin.api.util.Lock
51
+ import org.utbot.framework.plugin.api.util.LockFile
52
52
53
53
object UtTestsDialogProcessor {
54
54
private val logger = KotlinLogging .logger {}
@@ -122,150 +122,153 @@ object UtTestsDialogProcessor {
122
122
promise.onSuccess {
123
123
if (it.hasErrors() || it.isAborted)
124
124
return @onSuccess
125
- if (! Lock .lock()) {
126
- return @onSuccess
127
- }
128
125
129
126
(object : Task .Backgroundable (project, " Generate tests" ) {
130
127
131
128
override fun run (indicator : ProgressIndicator ) {
132
- val ldef = LifetimeDefinition ()
133
- ldef.onTermination { Lock .unlock() }
134
- ldef.terminateOnException { lifetime ->
135
- val secondsTimeout = TimeUnit .MILLISECONDS .toSeconds(model.timeout)
136
-
137
- indicator.isIndeterminate = false
138
- updateIndicator(indicator, ProgressRange .SOLVING , " Generate tests: read classes" , 0.0 )
139
-
140
- val buildPaths = ReadAction
141
- .nonBlocking<BuildPaths ?> { findPaths(model.srcClasses) }
142
- .executeSynchronously()
143
- ? : return
144
-
145
- val (buildDirs, classpath, classpathList, pluginJarsPath) = buildPaths
146
-
147
- val testSetsByClass = mutableMapOf<PsiClass , RdTestGenerationResult >()
148
- val psi2KClass = mutableMapOf<PsiClass , ClassId >()
149
- var processedClasses = 0
150
- val totalClasses = model.srcClasses.size
151
-
152
- val proc = EngineProcess (lifetime, project)
153
-
154
- proc.setupUtContext(buildDirs + classpathList)
155
- proc.createTestGenerator(
156
- buildDirs,
157
- classpath,
158
- pluginJarsPath.joinToString(separator = File .pathSeparator),
159
- JdkInfoService .provide()
160
- ) {
161
- ApplicationManager .getApplication().runReadAction(Computable {
162
- indicator.isCanceled
163
- })
164
- }
129
+ if (! LockFile .lock()) {
130
+ return
131
+ }
132
+ try {
133
+ val ldef = LifetimeDefinition ()
134
+ ldef.terminateOnException { lifetime ->
135
+ val secondsTimeout = TimeUnit .MILLISECONDS .toSeconds(model.timeout)
165
136
166
- for (srcClass in model.srcClasses) {
167
- val (methods, className) = DumbService .getInstance(project)
168
- .runReadActionInSmartMode(Computable {
169
- val canonicalName = srcClass.canonicalName
170
- val classId = proc.obtainClassId(canonicalName)
171
- psi2KClass[srcClass] = classId
172
-
173
- val srcMethods = if (model.extractMembersFromSrcClasses) {
174
- val chosenMethods = model.selectedMembers.filter { it.member is PsiMethod }
175
- val chosenNestedClasses =
176
- model.selectedMembers.mapNotNull { it.member as ? PsiClass }
177
- chosenMethods + chosenNestedClasses.flatMap {
178
- it.extractClassMethodsIncludingNested(false )
179
- }
180
- } else {
181
- srcClass.extractClassMethodsIncludingNested(false )
182
- }
183
- proc.findMethodsInClassMatchingSelected(classId, srcMethods) to srcClass.name
184
- })
137
+ indicator.isIndeterminate = false
138
+ updateIndicator(indicator, ProgressRange .SOLVING , " Generate tests: read classes" , 0.0 )
185
139
186
- if (methods.isEmpty()) {
187
- logger.error { " No methods matching selected found in class $className ." }
188
- continue
140
+ val buildPaths = ReadAction
141
+ .nonBlocking<BuildPaths ?> { findPaths(model.srcClasses) }
142
+ .executeSynchronously()
143
+ ? : return
144
+
145
+ val (buildDirs, classpath, classpathList, pluginJarsPath) = buildPaths
146
+
147
+ val testSetsByClass = mutableMapOf<PsiClass , RdTestGenerationResult >()
148
+ val psi2KClass = mutableMapOf<PsiClass , ClassId >()
149
+ var processedClasses = 0
150
+ val totalClasses = model.srcClasses.size
151
+
152
+ val proc = EngineProcess (lifetime, project)
153
+
154
+ proc.setupUtContext(buildDirs + classpathList)
155
+ proc.createTestGenerator(
156
+ buildDirs,
157
+ classpath,
158
+ pluginJarsPath.joinToString(separator = File .pathSeparator),
159
+ JdkInfoService .provide()
160
+ ) {
161
+ ApplicationManager .getApplication().runReadAction(Computable {
162
+ indicator.isCanceled
163
+ })
189
164
}
190
165
191
- if (totalClasses > 1 ) {
192
- updateIndicator(
193
- indicator,
194
- ProgressRange .SOLVING ,
195
- " Generate test cases for class $className " ,
196
- processedClasses.toDouble() / totalClasses
197
- )
198
- }
166
+ for (srcClass in model.srcClasses) {
167
+ val (methods, className) = DumbService .getInstance(project)
168
+ .runReadActionInSmartMode(Computable {
169
+ val canonicalName = srcClass.canonicalName
170
+ val classId = proc.obtainClassId(canonicalName)
171
+ psi2KClass[srcClass] = classId
172
+
173
+ val srcMethods = if (model.extractMembersFromSrcClasses) {
174
+ val chosenMethods = model.selectedMembers.filter { it.member is PsiMethod }
175
+ val chosenNestedClasses =
176
+ model.selectedMembers.mapNotNull { it.member as ? PsiClass }
177
+ chosenMethods + chosenNestedClasses.flatMap {
178
+ it.extractClassMethodsIncludingNested(false )
179
+ }
180
+ } else {
181
+ srcClass.extractClassMethodsIncludingNested(false )
182
+ }
183
+ proc.findMethodsInClassMatchingSelected(classId, srcMethods) to srcClass.name
184
+ })
199
185
200
- // set timeout for concrete execution and for generated tests
201
- UtSettings .concreteExecutionTimeoutInChildProcess =
202
- model.hangingTestsTimeout.timeoutMs
186
+ if (methods.isEmpty()) {
187
+ logger.error { " No methods matching selected found in class $className ." }
188
+ continue
189
+ }
203
190
204
- UtSettings .useCustomJavaDocTags =
205
- model.commentStyle == JavaDocCommentStyle .CUSTOM_JAVADOC_TAGS
191
+ if (totalClasses > 1 ) {
192
+ updateIndicator(
193
+ indicator,
194
+ ProgressRange .SOLVING ,
195
+ " Generate test cases for class $className " ,
196
+ processedClasses.toDouble() / totalClasses
197
+ )
198
+ }
206
199
207
- UtSettings .enableSummariesGeneration = model.enableSummariesGeneration
200
+ // set timeout for concrete execution and for generated tests
201
+ UtSettings .concreteExecutionTimeoutInChildProcess =
202
+ model.hangingTestsTimeout.timeoutMs
208
203
209
- val searchDirectory = ReadAction
210
- .nonBlocking<Path > {
211
- project.basePath?.let { Paths .get(it) }
212
- ? : Paths .get(srcClass.containingFile.virtualFile.parent.path)
213
- }
214
- .executeSynchronously()
204
+ UtSettings .useCustomJavaDocTags =
205
+ model.commentStyle == JavaDocCommentStyle .CUSTOM_JAVADOC_TAGS
215
206
216
- withStaticsSubstitutionRequired(true ) {
217
- val mockFrameworkInstalled = model.mockFramework?.isInstalled ? : true
218
-
219
- val rdGenerateResult = proc.generate(
220
- mockFrameworkInstalled,
221
- model.staticsMocking.isConfigured,
222
- model.conflictTriggers,
223
- methods,
224
- model.mockStrategy,
225
- model.chosenClassesToMockAlways,
226
- model.timeout,
227
- model.timeout,
228
- true ,
229
- UtSettings .useFuzzing,
230
- project.service<Settings >().fuzzingValue,
231
- searchDirectory.pathString
232
- )
233
-
234
- if (rdGenerateResult.notEmptyCases == 0 ) {
235
- if (model.srcClasses.size > 1 ) {
236
- logger.error { " Failed to generate any tests cases for class $className " }
207
+ UtSettings .enableSummariesGeneration = model.enableSummariesGeneration
208
+
209
+ val searchDirectory = ReadAction
210
+ .nonBlocking<Path > {
211
+ project.basePath?.let { Paths .get(it) }
212
+ ? : Paths .get(srcClass.containingFile.virtualFile.parent.path)
213
+ }
214
+ .executeSynchronously()
215
+
216
+ withStaticsSubstitutionRequired(true ) {
217
+ val mockFrameworkInstalled = model.mockFramework?.isInstalled ? : true
218
+
219
+ val rdGenerateResult = proc.generate(
220
+ mockFrameworkInstalled,
221
+ model.staticsMocking.isConfigured,
222
+ model.conflictTriggers,
223
+ methods,
224
+ model.mockStrategy,
225
+ model.chosenClassesToMockAlways,
226
+ model.timeout,
227
+ model.timeout,
228
+ true ,
229
+ UtSettings .useFuzzing,
230
+ project.service<Settings >().fuzzingValue,
231
+ searchDirectory.pathString
232
+ )
233
+
234
+ if (rdGenerateResult.notEmptyCases == 0 ) {
235
+ if (model.srcClasses.size > 1 ) {
236
+ logger.error { " Failed to generate any tests cases for class $className " }
237
+ } else {
238
+ showErrorDialogLater(
239
+ model.project,
240
+ errorMessage(className, secondsTimeout),
241
+ title = " Failed to generate unit tests for class $className "
242
+ )
243
+ }
237
244
} else {
238
- showErrorDialogLater(
239
- model.project,
240
- errorMessage(className, secondsTimeout),
241
- title = " Failed to generate unit tests for class $className "
242
- )
245
+ testSetsByClass[srcClass] = rdGenerateResult
243
246
}
244
- } else {
245
- testSetsByClass[srcClass] = rdGenerateResult
246
247
}
248
+ processedClasses++
247
249
}
248
- processedClasses++
249
- }
250
250
251
- if (processedClasses == 0 ) {
252
- invokeLater {
253
- Messages .showInfoMessage(
254
- model.project,
255
- " No methods for test generation were found among selected items" ,
256
- " No methods found"
257
- )
251
+ if (processedClasses == 0 ) {
252
+ invokeLater {
253
+ Messages .showInfoMessage(
254
+ model.project,
255
+ " No methods for test generation were found among selected items" ,
256
+ " No methods found"
257
+ )
258
+ }
259
+ return
258
260
}
259
- return
260
- }
261
- updateIndicator(indicator, ProgressRange .CODEGEN , " Generate code for tests" , 0.0 )
262
- // Commented out to generate tests for collected executions even if action was canceled.
263
- // indicator.checkCanceled()
261
+ updateIndicator(indicator, ProgressRange .CODEGEN , " Generate code for tests" , 0.0 )
262
+ // Commented out to generate tests for collected executions even if action was canceled.
263
+ // indicator.checkCanceled()
264
264
265
- invokeLater {
266
- generateTests(model, testSetsByClass, psi2KClass, proc, indicator)
267
- logger.info { " Generation complete" }
265
+ invokeLater {
266
+ generateTests(model, testSetsByClass, psi2KClass, proc, indicator)
267
+ logger.info { " Generation complete" }
268
+ }
268
269
}
270
+ } finally {
271
+ LockFile .unlock()
269
272
}
270
273
}
271
274
}).queue()
0 commit comments