Repository navigation
Conversation
| if (flakyList != null && flakyList.size <= i){ | ||
| break | ||
| } | ||
| val flakyItem = if (flakyList != null) flakyList[i] else null |
There was a problem hiding this comment.
If i equals flakyList.size, could accessing flakyList[i] here cause an index-out-of-bounds exception?
There was a problem hiding this comment.
Kotlin lists are zero-indexed, so flakyList[size] is out of bounds. Changing < to <= makes the loop break when i == flakyList.size, before reaching flakyList[i]. The previous condition missed this boundary case.
There was a problem hiding this comment.
I am not sure about this. If the sizes of merged and original differ, why do we return merged directly (its size may be greater or less than original)?
There was a problem hiding this comment.
Updated in 06ebbceb4c. The early return could miss element changes in later observations, so the merge now preserves the size difference while continuing to process shared indices.
For example, with original [1,2] and observations [1] then [9,2], the merged result is now [9] instead of [1].
Added regression tests for both observation orders, nested arrays, and generated assertions. All 68 related tests pass.
|
@arcuri82 this PR is ready to review. |
| break | ||
| } | ||
| if (flakyList != null && flakyList.size < i){ | ||
| if (flakyList != null && flakyList.size <= i){ |
There was a problem hiding this comment.
the i is from list, isn't it? shouldn't add at beggining of handleAssertionsOnList some explicit checks on the sizes of the two input data structures, and throw an IllegalArgumentException?
There was a problem hiding this comment.
hi, i is valid for list eg [1,2], but the flakyList may be shorter, eg, [3]. then in this case, the code is to ensure to avoid the IndexOutOfBoundsException when getting flakyList[i]
There was a problem hiding this comment.
so, could add a if(flakyList!=null && flakyList.size > list.size) throw IllegalArgumentException at the beginning of the function
There was a problem hiding this comment.
also, it is more readable when the incrementing index is on left side, ie i >= flakyList.size
| * @return whether the action is follow-up action | ||
| */ | ||
| fun isFollowUpAction(): Boolean{ | ||
| return path.toString() == "/" && id.contains(HTTP_CALL_LOCATION_FOLLOWUP_KEY) |
There was a problem hiding this comment.
is path.toString() == "/" necessary? looks like hardcoding the placeholder from HttpSemanticService`
| import org.evomaster.core.problem.rest.link.RestLink | ||
| import org.evomaster.core.problem.rest.param.PathParam | ||
| import org.evomaster.core.problem.rest.resource.ActionRToken | ||
| import org.evomaster.core.problem.rest.service.HttpSemanticsService.Companion.HTTP_CALL_LOCATION_FOLLOWUP_KEY |
There was a problem hiding this comment.
maybe this constant should be moved here in this class? as it might be used in different places in future, and then check forisFollowUpAction is here anyway
|
|
||
| /** | ||
| * @return whether the action is follow-up action | ||
| */ |
There was a problem hiding this comment.
in docs, should explain what a follow-up action is. also, if the main problem is the lack of valid RestPath, then the name "follow-up" is confusing here. maybe something like isDirectLocationAction, explaining it is an action that alwasy use full Location from a previous response, and ignore its RestPath
| val seq = seeMainExecutableActions() | ||
| while (cur >= 0){ | ||
| val found = seq[cur] | ||
| if (!found.isFollowUpAction()) |
There was a problem hiding this comment.
eh? isn't this just returning the first previous non-followup action? that can be incorrect. as those actions are bound, you can use the links to refer to the source action in RestCallAction fields
| /** | ||
| * for the follow-up action, get its previous valid rest action | ||
| */ | ||
| fun getActualPathForFollowUpAction(index: Int): RestPath?{ |
There was a problem hiding this comment.
what does Actual mean here? the name of this method feels confusing. isn't rather the path of the source of Location FUA depends on?
| private fun updateParamInfo(action: RestCallAction, tables: Map<TableId, Table>) { | ||
| val r = rm.getResourceNodeFromCluster(action.path.toString()) | ||
| private fun updateParamInfo(action: RestCallAction, path: RestPath?, tables: Map<TableId, Table>) { | ||
| val rPath = if (action.isFollowUpAction()) path else action.path |
There was a problem hiding this comment.
in the else, should throw exception if path!=null?
| } | ||
|
|
||
| val budget = (config.timeLimitInSeconds() * config.extraPhaseBudgetPercentage).toLong() | ||
| val extraPercentage = if (target == Phase.FLAKINESS) config.extraBudgetPercentageForDetectFlakiness else config.extraPhaseBudgetPercentage |
There was a problem hiding this comment.
this is confusing, as now extraPhaseBudgetPercentage is silently ignored for Flakiness. I would prefer something else like unboundBugetForFlakiness:Boolean where, if true, then no bduget checks are done for flakiness phase. false by default
| internal fun getSqlInsertionExecutionTimeMs() = sqlInsertionExecutionTimeMs | ||
| internal fun getSqlInsertionExecutionCount() = sqlInsertionExecutionCount | ||
| internal fun getReExecutionTimesMs(): List<Long> = reExecutionTimesMs.toList() | ||
| internal fun getReExecutionTimeMs() = reExecutionTimesMs.sum() |
There was a problem hiding this comment.
those 2 names only differ with a single s in the middle. confusing. maybe rename first as getAllReExecutionTimesMs and second as getSumOfReExecutionTimesMs
| @Cfg("Specify extra budget percentage of the search budget for flakiness detection phase." + | ||
| "A negative value indicates an unlimited time budget.") | ||
| @Min(-1.0) | ||
| var extraBudgetPercentageForDetectFlakiness = -1.0 |
There was a problem hiding this comment.
rather use unboundBugetForFlakiness. also, if this is left as it is, it would mean flakiness phase was always unbound by default?
…nstead of the first non-follow-up action
| break | ||
| } | ||
| if (flakyList != null && flakyList.size < i){ | ||
| if (flakyList != null && flakyList.size <= i){ |
There was a problem hiding this comment.
should rather have i >= flakyList.size with a if(flakyList!=null && flakyList.size > list.size) throw IllegalArgumentException. also add javadocs to explain how flakyList relates to list
| val locationId = seq[cur].usePreviousLocationId | ||
| cur = (cur - 1 downTo 0).firstOrNull { | ||
| val candidate = seq[it] | ||
| candidate.isPotentialActionForCreation() && candidate.creationLocationId() == locationId |
There was a problem hiding this comment.
why checking for isPotentialActionForCreation ? technically a Location could be unrelated to create
There was a problem hiding this comment.
if there is curently a limitation in the algorithm, could leave a TODO comment
Problem
FlakinessDetector.hasPhaseTimedOut()queriesPhase.SECURITYinstead ofPhase.FLAKINESS.ExecutionPhaseControllerretains timeout flags for completed phases. If the security phase has timed out, querying its flag returnstrueeven after the flakiness phase starts with a fresh timer. Consequently, the timeout guards in static inference and re-execution can stop immediately, skipping flakiness detection.Fix
Change the queried phase from
SECURITYtoFLAKINESS.This is a one-line fix. It preserves the existing phase-wide time budget and does not add configuration options, change timeout policy, or modify result handling.
Validation
EMConfigTest,RestCallResultTest, andFlakinessInferenceUtilTestpassed.ExecutionPhaseControllerpassed:SECURITYquery still returnstruein this same state.The targeted checks simulated elapsed time by adjusting the controller's start timestamp; they were run locally and are not included in this minimal diff.