Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Single Lincheck options class with testingTime(..) option #158

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from

Conversation

eupp
Copy link
Collaborator

@eupp eupp commented Apr 6, 2023

Closes #137, #150, #151

This PR deprecates StressOptions, ModelCheckingOption, and also StressCTest, ModelCheckingCTest annotations.
Instead, new class LincheckOptions is introduced to configure Lincheck run.
Configuration of scenarios number and invocations per iteration number is also deprecated.
Instead, now the preferred way to configure Lincheck run is through single testingTime option.

Adaptive strategy to adjust scenarios and invocations numbers dynamically during the run is implemented (see class Planner).
The implementation tracks the average execution time over last N invocations.
Using the average execution time, the estimated remaining time is computed.
If the estimated time is greater (smaller) that allocated testing time by an order of magnitude (K times),
number of invocations is multiplied (divided) by a constant K.
If the estimated time is greater (smaller) that allocated testing time (but not that significantly), number of scenarios is increased (decreased) by a constant I.

For debugging purposes, I also add logging of invocations count and execution time after each iteration.

Besides that, the following logic is implemented:

  • 25% of time during testing is allocated to stress strategy, 75% to model checking
  • if stress strategy discovers a bug, model checking strategy is run with the hope to reproduce trace.

As a backward compatibility (and for a transition period), I left the possibility to manually set strategy (stress or model checking), number of scenarios and number of invocations per scenario.

To configure strategy, I added mode option to LincheckOptions.
Currently it is visible to the end user, but perhaps we want to hide it.
Other deprecated options also left visible, we can hide them if necessary.

I have not touch existing tests. Some of them manually set number of scenarios/invocations.
For test classes derived from AbstractLincheckTest we can easily add new subset of tests for new behavior called testWithHybridStrategy.
It will allow us to test each strategy individually, as well as hybrid automatic strategy implemented in this PR.

@eupp eupp requested a review from ndkoval April 6, 2023 12:05
import org.jetbrains.kotlinx.lincheck.verifier.*
import org.jetbrains.kotlinx.lincheck.verifier.linearizability.*
import java.lang.reflect.*

/**
* Abstract configuration for different lincheck modes.
*/
@Deprecated(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also annotate with Kotlin's @Deprecated annotation as well. Let's use the ERROR level, thus, forcing users to update the code. Please also indicate here that both ModelChecking and Stress Options are deprecated and that LincheckOptions incorporates both these functionalities.

* we print the code location where this atomic method is called
* instead of going deeper inside it.
*/
private fun isTrustedPrimitive(className: String) =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to be here.

* (e.g., due to a switch to another thread), and omits all the details except for
* the method invocation result.
*/
fun verboseTrace(verboseTrace: Boolean = true) = apply {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to have it.

/**
* Set logging level, [DEFAULT_LOG_LEVEL] is used by default.
*/
fun logLevel(logLevel: LoggingLevel) = apply {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to have it in the API.

*
* @see ExecutionScenario.postExecution
*/
fun actorsAfter(actorsAfter: Int) = apply {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need this parameter.

*
* @see ExecutionScenario.initExecution
*/
fun actorsBefore(actorsBefore: Int) = apply {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need this parameter.

*
* @see ExecutionScenario.parallelExecution
*/
fun actorsPerThread(actorsPerThread: Int) = apply {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be operationsPerThread. Let's get rid of the word "actor".

private const val INVOCATIONS_LOWER_BOUND = 1_000

// upper bound of invocations allocated by iteration
private const val INVOCATIONS_UPPER_BOUND = 100_000
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it work well with the current model checker? I guess the tests will fail with OutOfMemoryError.

@Deprecated(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please deprecate with both Java's and Kotlin's @Deprecated annotation.

if (options.mode == LincheckMode.Hybrid && mode == LincheckMode.Stress) {
// try to reproduce an error trace with model checking strategy
createStrategy(LincheckMode.ModelChecking, testClass, minimizedFailure.scenario, testCfg, testStructure)
.run(verifier, MODEL_CHECKING_INVOCATIONS_COUNT)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make sure that if the model checking mode fails here (e.g., throws some exception due to non-determinism), the user still can get the output from the stress mode

@eupp eupp force-pushed the lincheck-options branch from b01ae8d to 83233a3 Compare April 24, 2023 18:59
@eupp eupp requested a review from ndkoval April 29, 2023 22:24
@eupp eupp force-pushed the lincheck-options branch from 6786928 to 26f9906 Compare June 1, 2023 13:47
@ndkoval ndkoval changed the title Single Lincheck options class and testingTime option Single Lincheck options class with testingTime(..) option Jun 16, 2023
@eupp eupp force-pushed the lincheck-options branch from 0bf9521 to 7c50db9 Compare July 17, 2023 16:39
@eupp eupp force-pushed the lincheck-options branch from 6911607 to 976d438 Compare August 17, 2023 12:15
@eupp
Copy link
Collaborator Author

eupp commented Aug 17, 2023

@ndkoval ready for re-review

@eupp
Copy link
Collaborator Author

eupp commented Aug 17, 2023

@ndkoval

I still have a small concern with respect to extensive use of internal API in tests. Maybe we should consider keeping some common options in public API?

Also, currently the following code pattern is used to access internal API in tests:

LincheckOptions {
    this as LincheckOptionsImpl
    maxThreads = 2
    maxOperationsInThread = 2
    mode = LincheckMode.ModelChecking
}

Maybe replace it with the following pattern? In my opinion it better reflects the intention here:

LincheckInternalOptions {
    maxThreads = 2
    maxOperationsInThread = 2
    mode = LincheckMode.ModelChecking
}

here, LincheckInternalOptions is renamed LincheckOptionsImpl class that implements LincheckOptions interface.

@ndkoval ndkoval linked an issue Jan 18, 2024 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add testingTime(..) option to configure Lincheck tests
3 participants