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

Object numeration mismatch fix #344

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions bootstrap/src/sun/nio/ch/lincheck/EventTracker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,5 @@ interface EventTracker {
fun beforeEvent(eventId: Int, type: String)
fun getEventId(): Int
fun setLastMethodCallEventId()
fun enumerateObjectsIfNeeded()
}
11 changes: 11 additions & 0 deletions bootstrap/src/sun/nio/ch/lincheck/Injections.java
Original file line number Diff line number Diff line change
Expand Up @@ -341,4 +341,15 @@ public static int getNextEventId(String type) {
public static void setLastMethodCallEventId() {
getEventTracker().setLastMethodCallEventId();
}

/**
* The Plugin traverses the test object when enabled before the trace is fully reported via `beforeEvent`
* method calls before each trace point. Thus, the Lincheck might see some object fields before it's appeared in the trace.
* This may lead to object numeration mismatch between the output with the plugin enabled and without.
* To avoid that, we traverse test object and enumerate all nested object recursively each time we collect a
* trace, so the numeration stays the same.
*/
public static void enumerateObjectsIfNeeded() {
getEventTracker().enumerateObjectsIfNeeded();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1328,6 +1328,15 @@ abstract class ManagedStrategy(
setBeforeEventId(lastMethodCall)
}

/**
* Enumerates recursevely all test object of trace collection is enabled.
* @see Injections.enumerateObjectsIfNeeded
*/
override fun enumerateObjectsIfNeeded() {
if (!collectTrace) return
enumerateObjects(runner.testInstance)
}

/**
* Set eventId of the [tracePoint] right after it is added to the trace.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,18 @@ internal open class ManagedStrategyMethodVisitor(

/**
* Injects `beforeEvent` method invocation if IDEA plugin is enabled.
* If the plugin is disabled, insert invocation of `enumerateObjectsIfNeeded` method. See its doc for more details.
*
* @param type type of the event, needed just for debugging.
* @param setMethodEventId a flag that identifies that method call event id set is required
*/
protected fun invokeBeforeEventIfPluginEnabled(type: String, setMethodEventId: Boolean = false) {
if (ideaPluginEnabled) {
adapter.invokeBeforeEvent(type, setMethodEventId)
} else {
adapter.invokeInIgnoredSection {
adapter.invokeStatic(Injections::enumerateObjectsIfNeeded)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,9 @@ internal fun GeneratorAdapter.invokeBeforeEvent(debugMessage: String, setMethodE
push(debugMessage)
invokeStatic(Injections::beforeEvent)
},
elseClause = {}
elseClause = {
invokeStatic(Injections::enumerateObjectsIfNeeded)
Copy link
Collaborator

Choose a reason for hiding this comment

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

This logic contradicts with the invokeBeforeEvent function name

}
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,16 @@ Detailed trace:
| counter.READ: 0 at BaseFailingTest.increment(BaseFailingTest.kt:30) | |
| counter.WRITE(1) at BaseFailingTest.increment(BaseFailingTest.kt:30) | |
| actionsForTrace() at BaseFailingTest.increment(BaseFailingTest.kt:31) | |
| atomicReference1.READ: AtomicReference#1 at AtomicReferencesFromMultipleFieldsTest.actionsForTrace(AtomicReferencesNamesTests.kt:98) | |
| atomicReference2.READ: AtomicReference#1 at AtomicReferencesFromMultipleFieldsTest.actionsForTrace(AtomicReferencesNamesTests.kt:98) | |
| AtomicReference#1.get(): Node#1 at AtomicReferencesFromMultipleFieldsTest.actionsForTrace(AtomicReferencesNamesTests.kt:98) | |
| AtomicReference#1.compareAndSet(Node#1,Node#2): true at AtomicReferencesFromMultipleFieldsTest.actionsForTrace(AtomicReferencesNamesTests.kt:98) | |
| atomicReference1.READ: AtomicReference#1 at AtomicReferencesFromMultipleFieldsTest.actionsForTrace(AtomicReferencesNamesTests.kt:97) | |
| atomicReference2.READ: AtomicReference#1 at AtomicReferencesFromMultipleFieldsTest.actionsForTrace(AtomicReferencesNamesTests.kt:97) | |
| AtomicReference#1.get(): Node#1 at AtomicReferencesFromMultipleFieldsTest.actionsForTrace(AtomicReferencesNamesTests.kt:97) | |
| AtomicReference#1.compareAndSet(Node#1,Node#2): true at AtomicReferencesFromMultipleFieldsTest.actionsForTrace(AtomicReferencesNamesTests.kt:97) | |
| result: 0 | |
| | counter.WRITE(1) at BaseFailingTest.increment(BaseFailingTest.kt:30) |
| | actionsForTrace() at BaseFailingTest.increment(BaseFailingTest.kt:31) |
| | atomicReference1.READ: AtomicReference#1 at AtomicReferencesFromMultipleFieldsTest.actionsForTrace(AtomicReferencesNamesTests.kt:98) |
| | atomicReference2.READ: AtomicReference#1 at AtomicReferencesFromMultipleFieldsTest.actionsForTrace(AtomicReferencesNamesTests.kt:98) |
| | AtomicReference#1.get(): Node#2 at AtomicReferencesFromMultipleFieldsTest.actionsForTrace(AtomicReferencesNamesTests.kt:98) |
| | AtomicReference#1.compareAndSet(Node#2,Node#3): true at AtomicReferencesFromMultipleFieldsTest.actionsForTrace(AtomicReferencesNamesTests.kt:98) |
| | atomicReference1.READ: AtomicReference#1 at AtomicReferencesFromMultipleFieldsTest.actionsForTrace(AtomicReferencesNamesTests.kt:97) |
| | atomicReference2.READ: AtomicReference#1 at AtomicReferencesFromMultipleFieldsTest.actionsForTrace(AtomicReferencesNamesTests.kt:97) |
| | AtomicReference#1.get(): Node#2 at AtomicReferencesFromMultipleFieldsTest.actionsForTrace(AtomicReferencesNamesTests.kt:97) |
| | AtomicReference#1.compareAndSet(Node#2,Node#3): true at AtomicReferencesFromMultipleFieldsTest.actionsForTrace(AtomicReferencesNamesTests.kt:97) |
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is there any difference in this output besides the line numbers?

| | result: 0 |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
Loading