GP-856: Fixed tests for dbgeng, added tests for dbgmodel

This commit is contained in:
Dan 2021-04-20 16:08:07 -04:00
parent a61c2e1400
commit f077adfffb
76 changed files with 917 additions and 225 deletions

View file

@ -218,7 +218,7 @@ public abstract class AbstractDebuggerObjectModel implements SpiDebuggerObjectMo
public void removeExisting(List<String> path) {
TargetObject existing = getModelObject(path);
// It had better be. This also checks for null
// It's best if the implementation has already removed it, but just in case....
if (existing == null) {
return;
}
@ -230,15 +230,27 @@ public abstract class AbstractDebuggerObjectModel implements SpiDebuggerObjectMo
if (!path.equals(existing.getPath())) {
return; // Is a link
}
if (parent instanceof DefaultTargetObject<?, ?>) { // It had better be
DefaultTargetObject<?, ?> dtoParent = (DefaultTargetObject<?, ?>) parent;
if (PathUtils.isIndex(path)) {
dtoParent.changeElements(List.of(PathUtils.getIndex(path)), List.of(), "Replaced");
}
else {
assert PathUtils.isName(path);
dtoParent.changeAttributes(List.of(PathUtils.getKey(path)), Map.of(), "Replaced");
}
if (!(parent instanceof SpiTargetObject)) { // It had better be
Msg.error(this, "Could not remove existing object " + existing +
", because parent is not an SpiTargetObject");
return;
}
SpiTargetObject spiParent = (SpiTargetObject) parent;
SpiTargetObject delegate = spiParent.getDelegate();
if (!(delegate instanceof DefaultTargetObject<?, ?>)) { // It had better be :)
Msg.error(this, "Could not remove existing object " + existing +
", because its parent's delegate is not a DefaultTargetObject");
return;
}
DefaultTargetObject<?, ?> dtoParent = (DefaultTargetObject<?, ?>) delegate;
if (PathUtils.isIndex(path)) {
dtoParent.changeElements(List.of(PathUtils.getIndex(path)), List.of(),
"Replaced");
}
else {
assert PathUtils.isName(path);
dtoParent.changeAttributes(List.of(PathUtils.getKey(path)), Map.of(),
"Replaced");
}
}

View file

@ -319,9 +319,9 @@ public class DefaultTargetObject<E extends TargetObject, P extends TargetObject>
Delta<E, E> delta;
synchronized (model.lock) {
delta = Delta.computeAndSet(this.elements, elements, Delta.SAME);
getSchema().validateElementDelta(getPath(), delta, enforcesStrictSchema());
doInvalidateElements(delta.removed, reason);
}
getSchema().validateElementDelta(getPath(), delta, enforcesStrictSchema());
doInvalidateElements(delta.removed, reason);
if (!delta.isEmpty()) {
updateCallbackElements(delta);
listeners.fire.elementsChanged(getProxy(), delta.getKeysRemoved(), delta.added);
@ -361,9 +361,9 @@ public class DefaultTargetObject<E extends TargetObject, P extends TargetObject>
Delta<E, E> delta;
synchronized (model.lock) {
delta = Delta.apply(this.elements, remove, add, Delta.SAME);
getSchema().validateElementDelta(getPath(), delta, enforcesStrictSchema());
doInvalidateElements(delta.removed, reason);
}
getSchema().validateElementDelta(getPath(), delta, enforcesStrictSchema());
doInvalidateElements(delta.removed, reason);
if (!delta.isEmpty()) {
updateCallbackElements(delta);
listeners.fire.elementsChanged(getProxy(), delta.getKeysRemoved(), delta.added);
@ -497,9 +497,9 @@ public class DefaultTargetObject<E extends TargetObject, P extends TargetObject>
Delta<Object, ?> delta;
synchronized (model.lock) {
delta = Delta.computeAndSet(this.attributes, attributes, Delta.EQUAL);
getSchema().validateAttributeDelta(getPath(), delta, enforcesStrictSchema());
doInvalidateAttributes(delta.removed, reason);
}
getSchema().validateAttributeDelta(getPath(), delta, enforcesStrictSchema());
doInvalidateAttributes(delta.removed, reason);
if (!delta.isEmpty()) {
updateCallbackAttributes(delta);
listeners.fire.attributesChanged(getProxy(), delta.getKeysRemoved(), delta.added);
@ -556,9 +556,9 @@ public class DefaultTargetObject<E extends TargetObject, P extends TargetObject>
Delta<Object, ?> delta;
synchronized (model.lock) {
delta = Delta.apply(this.attributes, remove, add, Delta.EQUAL);
getSchema().validateAttributeDelta(getPath(), delta, enforcesStrictSchema());
doInvalidateAttributes(delta.removed, reason);
}
getSchema().validateAttributeDelta(getPath(), delta, enforcesStrictSchema());
doInvalidateAttributes(delta.removed, reason);
if (!delta.isEmpty()/* && !reason.equals("Default")*/) {
updateCallbackAttributes(delta);
listeners.fire.attributesChanged(getProxy(), delta.getKeysRemoved(), delta.added);

View file

@ -26,4 +26,13 @@ public interface SpiTargetObject extends TargetObject, InvalidatableTargetObject
//Map<String, ? extends SpiTargetObject> getCachedElements();
boolean enforcesStrictSchema();
/**
* If this internal implementation is a proxy, get its delegate
*
* @return the delegate, or this same object
*/
default SpiTargetObject getDelegate() {
return this;
}
}

View file

@ -16,8 +16,7 @@
package ghidra.dbg.test;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeNotNull;
import static org.junit.Assume.assumeTrue;
import static org.junit.Assume.*;
import java.util.List;
import java.util.Set;
@ -150,6 +149,7 @@ public abstract class AbstractDebuggerModelActivationTest extends AbstractDebugg
assertActiveViaInterpreter(obj, interpreter);
}
}
}
@Test
@ -185,8 +185,8 @@ public abstract class AbstractDebuggerModelActivationTest extends AbstractDebugg
m.build();
TargetFocusScope focusScope = findFocusScope();
TargetInterpreter interpreter = findInterpreter();
Set<TargetObject> activatable = getActivatableThings();
TargetInterpreter interpreter = findInterpreter();
for (TargetObject obj : activatable) {
activateViaInterpreter(obj, interpreter);
retryVoid(() -> {

View file

@ -16,8 +16,7 @@
package ghidra.dbg.test;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeNotNull;
import static org.junit.Assume.assumeTrue;
import static org.junit.Assume.*;
import java.util.*;
import java.util.Map.Entry;
@ -511,8 +510,8 @@ public abstract class AbstractDebuggerModelBreakpointsTest extends AbstractDebug
assumeTrue(m.hasInterpreter());
m.build();
TargetInterpreter interpreter = findInterpreter();
Set<TargetBreakpointLocation> locs = createLocations();
TargetInterpreter interpreter = findInterpreter();
runToggleTestViaInterpreter(locs.stream()
.map(l -> l.getSpecification().as(TargetTogglable.class))
.collect(Collectors.toSet()),
@ -535,8 +534,8 @@ public abstract class AbstractDebuggerModelBreakpointsTest extends AbstractDebug
assumeTrue(m.hasInterpreter());
m.build();
TargetInterpreter interpreter = findInterpreter();
Set<TargetBreakpointLocation> locs = createLocations();
TargetInterpreter interpreter = findInterpreter();
runToggleTestViaInterpreter(
locs.stream().map(l -> l.as(TargetTogglable.class)).collect(Collectors.toSet()),
interpreter);
@ -587,8 +586,8 @@ public abstract class AbstractDebuggerModelBreakpointsTest extends AbstractDebug
assumeTrue(m.hasInterpreter());
m.build();
TargetInterpreter interpreter = findInterpreter();
Set<TargetBreakpointLocation> locs = createLocations();
TargetInterpreter interpreter = findInterpreter();
runDeleteTestViaInterpreter(locs.stream()
.map(l -> l.getSpecification().as(TargetDeletable.class))
.collect(Collectors.toSet()),

View file

@ -92,13 +92,26 @@ public abstract class AbstractDebuggerModelInterpreterTest extends AbstractDebug
*/
protected abstract String getKillCommand(TargetProcess process);
/**
* Perform an pre-test actions to ensure an interpreter exists where expected
*
* <p>
* The model will have been built already. This method is invoked immediately preceding
* {@link #findInterpreter()}
*
* @throws Throwable if anything goes wrong
*/
protected void ensureInterpreterAvailable() throws Throwable {
}
@Test
public void testInterpreterIsWhereExpected() throws Throwable {
List<String> expectedInterpreterPath = getExpectedInterpreterPath();
assumeNotNull(expectedInterpreterPath);
m.build();
TargetInterpreter interpreter = m.find(TargetInterpreter.class, List.of());
ensureInterpreterAvailable();
TargetInterpreter interpreter = findInterpreter();
assertEquals(expectedInterpreterPath, interpreter.getPath());
}
@ -126,7 +139,8 @@ public abstract class AbstractDebuggerModelInterpreterTest extends AbstractDebug
assumeNotNull(cmd);
m.build();
TargetInterpreter interpreter = m.find(TargetInterpreter.class, List.of());
ensureInterpreterAvailable();
TargetInterpreter interpreter = findInterpreter();
runTestExecute(interpreter, cmd);
}
@ -161,7 +175,8 @@ public abstract class AbstractDebuggerModelInterpreterTest extends AbstractDebug
assumeNotNull(cmd);
m.build();
TargetInterpreter interpreter = m.find(TargetInterpreter.class, List.of());
ensureInterpreterAvailable();
TargetInterpreter interpreter = findInterpreter();
runTestExecuteCapture(interpreter, cmd);
}
@ -176,7 +191,8 @@ public abstract class AbstractDebuggerModelInterpreterTest extends AbstractDebug
assumeNotNull(cmd);
m.build();
TargetInterpreter interpreter = m.find(TargetInterpreter.class, List.of());
ensureInterpreterAvailable();
TargetInterpreter interpreter = findInterpreter();
runTestExecute(interpreter, cmd);
}
@ -203,6 +219,7 @@ public abstract class AbstractDebuggerModelInterpreterTest extends AbstractDebug
assumeTrue(m.hasProcessContainer());
m.build();
ensureInterpreterAvailable();
TargetInterpreter interpreter = findInterpreter();
TargetProcess process = runTestLaunchViaInterpreterShowsInProcessContainer(interpreter);
@ -233,6 +250,7 @@ public abstract class AbstractDebuggerModelInterpreterTest extends AbstractDebug
m.build();
dummy = specimen.runDummy();
ensureInterpreterAvailable();
TargetInterpreter interpreter = findInterpreter();
TargetProcess process = runTestAttachViaInterpreterShowsInProcessContainer(interpreter);

View file

@ -16,7 +16,7 @@
package ghidra.dbg.test;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeNotNull;
import static org.junit.Assume.*;
import java.util.*;
import java.util.concurrent.CompletableFuture;
@ -109,7 +109,7 @@ public abstract class AbstractDebuggerModelSteppableTest extends AbstractDebugge
* @return the window in milliseconds
*/
protected long getDebounceWindowMs() {
return 1000;
return 5000;
}
enum CallbackType {