mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-24 03:09:36 +08:00
GP-829: Removing processContainer concept from tests.
This commit is contained in:
+3
-8
@@ -15,13 +15,14 @@
|
||||
*/
|
||||
package agent.dbgeng.model;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.dbg.target.*;
|
||||
import ghidra.dbg.target.TargetBreakpointSpec.TargetBreakpointKind;
|
||||
import ghidra.dbg.target.TargetBreakpointSpecContainer.TargetBreakpointKindSet;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.target.TargetStackFrame;
|
||||
import ghidra.dbg.test.*;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
import ghidra.program.model.address.*;
|
||||
@@ -79,10 +80,4 @@ public abstract class AbstractModelForDbgengBreakpointsTest
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TargetObject findProcessContainer() throws Throwable {
|
||||
return m.findContainer(TargetProcess.class, PathUtils.parse("Sessions[0]"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ public abstract class AbstractModelForDbgengFrameFocusTest
|
||||
|
||||
return retry(() -> {
|
||||
Map<List<String>, TargetStackFrame> frames =
|
||||
m.findAll(TargetStackFrame.class, seedPath());
|
||||
m.findAll(TargetStackFrame.class, seedPath(), true);
|
||||
assertTrue(frames.size() >= 3);
|
||||
return Set.copyOf(frames.values());
|
||||
}, List.of(AssertionError.class));
|
||||
|
||||
+11
@@ -17,6 +17,7 @@ package agent.dbgeng.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.dbg.target.TargetProcess;
|
||||
import ghidra.dbg.test.AbstractDebuggerModelInterpreterTest;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
|
||||
@@ -48,6 +49,16 @@ public abstract class AbstractModelForDbgengInterpreterTest
|
||||
return ".attach " + Long.toHexString(dummy.pid);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDetachCommand(TargetProcess process) {
|
||||
return ".detach";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getKillCommand(TargetProcess process) {
|
||||
return ".kill";
|
||||
}
|
||||
|
||||
@Override
|
||||
public DebuggerTestSpecimen getAttachSpecimen() {
|
||||
return WindowsSpecimen.NOTEPAD;
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ public abstract class AbstractModelForDbgengProcessFocusTest
|
||||
}
|
||||
return retry(() -> {
|
||||
Map<List<String>, TargetProcess> found =
|
||||
m.findAll(TargetProcess.class, PathUtils.parse("Sessions[0]"));
|
||||
m.findAll(TargetProcess.class, PathUtils.parse("Sessions[0]"), true);
|
||||
assertEquals(count, found.size());
|
||||
return Set.copyOf(found.values());
|
||||
}, List.of(AssertionError.class));
|
||||
|
||||
+1
-11
@@ -20,7 +20,7 @@ import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.dbg.target.*;
|
||||
import ghidra.dbg.target.TargetEnvironment;
|
||||
import ghidra.dbg.target.TargetMethod.TargetParameterMap;
|
||||
import ghidra.dbg.test.AbstractDebuggerModelAttacherTest;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
@@ -28,21 +28,11 @@ import ghidra.dbg.util.PathUtils;
|
||||
public abstract class AbstractModelForDbgengRootAttacherTest
|
||||
extends AbstractDebuggerModelAttacherTest {
|
||||
|
||||
@Override
|
||||
protected TargetObject findProcessContainer() throws Throwable {
|
||||
return m.findContainer(TargetProcess.class, PathUtils.parse("Sessions[0]"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getExpectedAttachableContainerPath() {
|
||||
return List.of("Available");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getExpectedProcessesContainerPath() {
|
||||
return PathUtils.parse("Sessions[0].Processes");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getExpectedAttacherPath() {
|
||||
return PathUtils.parse("");
|
||||
|
||||
+1
-11
@@ -21,7 +21,7 @@ import static org.junit.Assert.assertTrue;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import ghidra.dbg.target.*;
|
||||
import ghidra.dbg.target.TargetEnvironment;
|
||||
import ghidra.dbg.target.TargetMethod.ParameterDescription;
|
||||
import ghidra.dbg.target.TargetMethod.TargetParameterMap;
|
||||
import ghidra.dbg.test.AbstractDebuggerModelLauncherTest;
|
||||
@@ -30,16 +30,6 @@ import ghidra.dbg.util.PathUtils;
|
||||
public abstract class AbstractModelForDbgengRootLauncherTest
|
||||
extends AbstractDebuggerModelLauncherTest {
|
||||
|
||||
@Override
|
||||
protected TargetObject findProcessContainer() throws Throwable {
|
||||
return m.findContainer(TargetProcess.class, PathUtils.parse("Sessions[0]"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getExpectedProcessesContainerPath() {
|
||||
return PathUtils.parse("Sessions[0].Processes");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getExpectedLauncherPath() {
|
||||
return PathUtils.parse("");
|
||||
|
||||
-8
@@ -15,19 +15,11 @@
|
||||
*/
|
||||
package agent.dbgeng.model;
|
||||
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.target.TargetProcess;
|
||||
import ghidra.dbg.test.AbstractDebuggerModelScenarioCloneExitTest;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
|
||||
public abstract class AbstractModelForDbgengScenarioCloneExitTest
|
||||
extends AbstractDebuggerModelScenarioCloneExitTest {
|
||||
|
||||
@Override
|
||||
protected TargetObject findProcessContainer() throws Throwable {
|
||||
return m.findContainer(TargetProcess.class, PathUtils.parse("Sessions[0]"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DebuggerTestSpecimen getSpecimen() {
|
||||
return WindowsSpecimen.CREATE_THREAD_EXIT;
|
||||
|
||||
+1
-7
@@ -18,18 +18,12 @@ package agent.dbgeng.model;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import ghidra.dbg.target.*;
|
||||
import ghidra.dbg.target.TargetEnvironment;
|
||||
import ghidra.dbg.test.AbstractDebuggerModelScenarioForkExitTest;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
|
||||
public abstract class AbstractModelForDbgengScenarioForkExitTest
|
||||
extends AbstractDebuggerModelScenarioForkExitTest {
|
||||
|
||||
@Override
|
||||
protected TargetObject findProcessContainer() throws Throwable {
|
||||
return m.findContainer(TargetProcess.class, PathUtils.parse("Sessions[0]"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DebuggerTestSpecimen getSpecimen() {
|
||||
return WindowsSpecimen.CREATE_PROCESS;
|
||||
|
||||
-5
@@ -29,11 +29,6 @@ import ghidra.program.model.address.Address;
|
||||
public abstract class AbstractModelForDbgengScenarioMemoryTest
|
||||
extends AbstractDebuggerModelScenarioMemoryTest {
|
||||
|
||||
@Override
|
||||
protected TargetObject findProcessContainer() throws Throwable {
|
||||
return m.findContainer(TargetProcess.class, PathUtils.parse("Sessions[0]"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WindowsSpecimen getSpecimen() {
|
||||
return WindowsSpecimen.PRINT;
|
||||
|
||||
-5
@@ -31,11 +31,6 @@ public abstract class AbstractModelForDbgengScenarioStackTest
|
||||
List.of("break_here", "funcC", "funcB", "funcA");
|
||||
protected NavigableMap<Address, String> symbolsByAddress = new TreeMap<>();
|
||||
|
||||
@Override
|
||||
protected TargetObject findProcessContainer() throws Throwable {
|
||||
return m.findContainer(TargetProcess.class, PathUtils.parse("Sessions[0]"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WindowsSpecimen getSpecimen() {
|
||||
return WindowsSpecimen.STACK;
|
||||
|
||||
-7
@@ -20,19 +20,12 @@ import static org.junit.Assert.assertEquals;
|
||||
import java.util.Map;
|
||||
|
||||
import agent.dbgeng.model.impl.DbgModelTargetProcessImpl;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.target.TargetProcess;
|
||||
import ghidra.dbg.test.AbstractDebuggerModelScenarioRegistersTest;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
|
||||
public abstract class AbstractModelForDbgengScenarioX64RegistersTest
|
||||
extends AbstractDebuggerModelScenarioRegistersTest {
|
||||
|
||||
@Override
|
||||
protected TargetObject findProcessContainer() throws Throwable {
|
||||
return m.findContainer(TargetProcess.class, PathUtils.parse("Sessions[0]"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DebuggerTestSpecimen getSpecimen() {
|
||||
return WindowsSpecimen.REGISTERS;
|
||||
|
||||
-8
@@ -17,19 +17,11 @@ package agent.dbgeng.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.target.TargetProcess;
|
||||
import ghidra.dbg.test.*;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
|
||||
public abstract class AbstractModelForDbgengSteppableTest extends AbstractDebuggerModelSteppableTest
|
||||
implements ProvidesTargetViaLaunchSpecimen {
|
||||
|
||||
@Override
|
||||
protected TargetObject findProcessContainer() throws Throwable {
|
||||
return m.findContainer(TargetProcess.class, PathUtils.parse("Sessions[0]"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractDebuggerModelTest getTest() {
|
||||
return this;
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ public abstract class AbstractModelForDbgengThreadFocusTest
|
||||
}
|
||||
return retry(() -> {
|
||||
Map<List<String>, TargetThread> found =
|
||||
m.findAll(TargetThread.class, PathUtils.parse("Sessions[0]"));
|
||||
m.findAll(TargetThread.class, PathUtils.parse("Sessions[0]"), true);
|
||||
assertEquals(count, found.size());
|
||||
return Set.copyOf(found.values());
|
||||
}, List.of(AssertionError.class));
|
||||
|
||||
-7
@@ -18,8 +18,6 @@ package agent.dbgeng.model;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.target.TargetProcess;
|
||||
import ghidra.dbg.test.*;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
|
||||
@@ -37,11 +35,6 @@ public abstract class AbstractModelForDbgengX64RegistersTest
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TargetObject findProcessContainer() throws Throwable {
|
||||
return m.findContainer(TargetProcess.class, PathUtils.parse("Sessions[0]"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getExpectedRegisterBankPath(List<String> threadPath) {
|
||||
return PathUtils.extend(threadPath, PathUtils.parse("Registers"));
|
||||
|
||||
+1
-2
@@ -100,7 +100,6 @@ public enum WindowsSpecimen implements DebuggerTestSpecimen, DebuggerModelTestUt
|
||||
|
||||
public String getBinModuleName() {
|
||||
return getShortName(getCommandLine().split("\\s+")[0]);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -109,7 +108,7 @@ public enum WindowsSpecimen implements DebuggerTestSpecimen, DebuggerModelTestUt
|
||||
// NB. ShellUtils.parseArgs removes the \s. Not good.
|
||||
String expected = getBinModuleName();
|
||||
Collection<TargetModule> modules =
|
||||
test.m.findAll(TargetModule.class, process.getPath()).values();
|
||||
test.m.findAll(TargetModule.class, process.getPath(), true).values();
|
||||
return modules.stream()
|
||||
.anyMatch(m -> expected.equalsIgnoreCase(getShortName(m.getModuleName())));
|
||||
}
|
||||
|
||||
-5
@@ -31,11 +31,6 @@ public abstract class AbstractModelForGdbAttacherTest extends AbstractDebuggerMo
|
||||
return List.of("Available");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getExpectedProcessesContainerPath() {
|
||||
return List.of("Inferiors");
|
||||
}
|
||||
|
||||
@Override
|
||||
public DebuggerTestSpecimen getAttachSpecimen() {
|
||||
return GdbLinuxSpecimen.DD;
|
||||
|
||||
+11
@@ -17,6 +17,7 @@ package agent.gdb.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.dbg.target.TargetProcess;
|
||||
import ghidra.dbg.test.AbstractDebuggerModelInterpreterTest;
|
||||
|
||||
public abstract class AbstractModelForGdbInterpreterTest
|
||||
@@ -41,6 +42,16 @@ public abstract class AbstractModelForGdbInterpreterTest
|
||||
return "attach " + dummy.pid;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDetachCommand(TargetProcess process) {
|
||||
return "detach";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getKillCommand(TargetProcess process) {
|
||||
return "kill";
|
||||
}
|
||||
|
||||
@Override
|
||||
public DebuggerTestSpecimen getAttachSpecimen() {
|
||||
return GdbLinuxSpecimen.DD;
|
||||
|
||||
-6
@@ -18,7 +18,6 @@ package agent.gdb.model;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import ghidra.dbg.target.TargetEnvironment;
|
||||
@@ -28,11 +27,6 @@ import ghidra.dbg.test.AbstractDebuggerModelLauncherTest;
|
||||
|
||||
public abstract class AbstractModelForGdbLauncherTest extends AbstractDebuggerModelLauncherTest {
|
||||
|
||||
@Override
|
||||
public List<String> getExpectedProcessesContainerPath() {
|
||||
return List.of("Inferiors");
|
||||
}
|
||||
|
||||
@Override
|
||||
public DebuggerTestSpecimen getLaunchSpecimen() {
|
||||
return GdbLinuxSpecimen.ECHO_HW;
|
||||
|
||||
+2
-2
@@ -21,8 +21,7 @@ import java.awt.event.MouseEvent;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.*;
|
||||
|
||||
import com.google.common.collect.Range;
|
||||
|
||||
@@ -489,6 +488,7 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("This action is hidden until supported")
|
||||
public void testActionCaptureTypes() throws Exception {
|
||||
assertFalse(modulesProvider.actionCaptureTypes.isEnabled());
|
||||
createTestModel();
|
||||
|
||||
+8
-2
@@ -26,6 +26,7 @@ import ghidra.dbg.target.schema.EnumerableTargetObjectSchema;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
import ghidra.lifecycle.Internal;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.datastruct.ListenerSet;
|
||||
|
||||
/**
|
||||
@@ -245,8 +246,13 @@ public abstract class AbstractTargetObject<P extends TargetObject> implements Sp
|
||||
valid = false;
|
||||
model.objectInvalidated(getProxy());
|
||||
listeners.fire.invalidated(getProxy(), branch, reason);
|
||||
listeners.clear();
|
||||
listeners.clearChained();
|
||||
CompletableFuture.runAsync(() -> {
|
||||
listeners.clear();
|
||||
listeners.clearChained();
|
||||
}, model.clientExecutor).exceptionally(ex -> {
|
||||
Msg.error(this, "Error emptying invalidated object's listener set: ", ex);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
protected void doInvalidateElements(Map<String, ?> elems, String reason) {
|
||||
|
||||
+18
-67
@@ -16,7 +16,8 @@
|
||||
package ghidra.dbg.test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assume.*;
|
||||
import static org.junit.Assume.assumeNotNull;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.Collection;
|
||||
@@ -33,7 +34,6 @@ import ghidra.dbg.error.DebuggerIllegalArgumentException;
|
||||
import ghidra.dbg.target.*;
|
||||
import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState;
|
||||
import ghidra.dbg.target.TargetMethod.TargetParameterMap;
|
||||
import ghidra.dbg.testutil.ElementTrackingListener;
|
||||
import ghidra.program.model.address.AddressFactory;
|
||||
|
||||
public abstract class AbstractDebuggerModelAttacherTest extends AbstractDebuggerModelTest
|
||||
@@ -47,10 +47,6 @@ public abstract class AbstractDebuggerModelAttacherTest extends AbstractDebugger
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<String> getExpectedProcessesContainerPath() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract TargetParameterMap getExpectedAttachParameters();
|
||||
|
||||
public abstract void assertEnvironment(TargetEnvironment environment);
|
||||
@@ -65,16 +61,6 @@ public abstract class AbstractDebuggerModelAttacherTest extends AbstractDebugger
|
||||
assertEquals(expectedAttacherPath, attacher.getPath());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessContainerIsWhereExpected() throws Throwable {
|
||||
List<String> expectedProcessContainerPath = getExpectedProcessesContainerPath();
|
||||
assumeNotNull(expectedProcessContainerPath);
|
||||
m.build();
|
||||
|
||||
TargetObject container = findProcessContainer();
|
||||
assertEquals(expectedProcessContainerPath, container.getPath());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAttachableContainerIsWhereExpected() throws Throwable {
|
||||
List<String> expectedAttachableContainerPath = getExpectedAttachableContainerPath();
|
||||
@@ -195,12 +181,12 @@ public abstract class AbstractDebuggerModelAttacherTest extends AbstractDebugger
|
||||
runTestAttachByObjBogusThrowsException(attacher);
|
||||
}
|
||||
|
||||
protected void runTestAttachByPidThenDetach(TargetAttacher attacher, TargetObject container)
|
||||
protected void runTestAttachByPidThenDetach(TargetAttacher attacher)
|
||||
throws Throwable {
|
||||
DebuggerTestSpecimen specimen = getAttachSpecimen();
|
||||
assertNull(getProcessRunning(container, specimen, this));
|
||||
assertNull(getProcessRunning(specimen, this));
|
||||
runTestAttachByPid(attacher);
|
||||
runTestDetach(container, specimen);
|
||||
runTestDetach(specimen);
|
||||
assertTrue(dummy.process.isAlive());
|
||||
}
|
||||
|
||||
@@ -212,16 +198,15 @@ public abstract class AbstractDebuggerModelAttacherTest extends AbstractDebugger
|
||||
dummy = specimen.runDummy();
|
||||
|
||||
TargetAttacher attacher = findAttacher();
|
||||
TargetObject container = findProcessContainer();
|
||||
runTestAttachByPidThenDetach(attacher, container);
|
||||
runTestAttachByPidThenDetach(attacher);
|
||||
}
|
||||
|
||||
protected void runTestAttachByPidThenKill(TargetAttacher attacher, TargetObject container)
|
||||
protected void runTestAttachByPidThenKill(TargetAttacher attacher)
|
||||
throws Throwable {
|
||||
DebuggerTestSpecimen specimen = getAttachSpecimen();
|
||||
assertNull(getProcessRunning(container, specimen, this));
|
||||
assertNull(getProcessRunning(specimen, this));
|
||||
runTestAttachByPid(attacher);
|
||||
runTestKill(container, specimen);
|
||||
runTestKill(specimen);
|
||||
retryVoid(() -> assertFalse(dummy.process.isAlive()), List.of(AssertionError.class));
|
||||
}
|
||||
|
||||
@@ -233,16 +218,14 @@ public abstract class AbstractDebuggerModelAttacherTest extends AbstractDebugger
|
||||
dummy = specimen.runDummy();
|
||||
|
||||
TargetAttacher attacher = findAttacher();
|
||||
TargetObject container = findProcessContainer();
|
||||
runTestAttachByPidThenKill(attacher, container);
|
||||
runTestAttachByPidThenKill(attacher);
|
||||
}
|
||||
|
||||
protected void runTestAttachByPidThenResumeInterrupt(TargetAttacher attacher,
|
||||
TargetObject container) throws Throwable {
|
||||
protected void runTestAttachByPidThenResumeInterrupt(TargetAttacher attacher) throws Throwable {
|
||||
DebuggerTestSpecimen specimen = getAttachSpecimen();
|
||||
assertNull(getProcessRunning(container, specimen, this));
|
||||
assertNull(getProcessRunning(specimen, this));
|
||||
runTestAttachByPid(attacher);
|
||||
runTestResumeInterruptMany(container, specimen, 3);
|
||||
runTestResumeInterruptMany(specimen, 3);
|
||||
assertTrue(dummy.process.isAlive());
|
||||
}
|
||||
|
||||
@@ -254,16 +237,14 @@ public abstract class AbstractDebuggerModelAttacherTest extends AbstractDebugger
|
||||
dummy = specimen.runDummy();
|
||||
|
||||
TargetAttacher attacher = findAttacher();
|
||||
TargetObject container = findProcessContainer();
|
||||
runTestAttachByPidThenResumeInterrupt(attacher, container);
|
||||
runTestAttachByPidThenResumeInterrupt(attacher);
|
||||
}
|
||||
|
||||
protected void runTestAttachShowsInProcessContainer(TargetAttacher attacher,
|
||||
TargetObject container) throws Throwable {
|
||||
protected void runTestAttachShowsInProcessContainer(TargetAttacher attacher) throws Throwable {
|
||||
DebuggerTestSpecimen specimen = getAttachSpecimen();
|
||||
assertNull(getProcessRunning(container, specimen, this));
|
||||
assertNull(getProcessRunning(specimen, this));
|
||||
runTestAttachByPid(attacher);
|
||||
retryForProcessRunning(container, specimen, this);
|
||||
retryForProcessRunning(specimen, this);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -274,36 +255,6 @@ public abstract class AbstractDebuggerModelAttacherTest extends AbstractDebugger
|
||||
dummy = specimen.runDummy();
|
||||
|
||||
TargetAttacher attacher = findAttacher();
|
||||
TargetObject container = findProcessContainer();
|
||||
runTestAttachShowsInProcessContainer(attacher, container);
|
||||
}
|
||||
|
||||
protected void runTestAttachShowsInProcessContainerViaListener(TargetAttacher attacher,
|
||||
TargetObject container) throws Throwable {
|
||||
DebuggerTestSpecimen specimen = getAttachSpecimen();
|
||||
ElementTrackingListener<? extends TargetProcess> procListener =
|
||||
new ElementTrackingListener<>(TargetProcess.class);
|
||||
container.addListener(procListener);
|
||||
// NB. Have to express interest, otherwise model is not obligated to invoke listener
|
||||
Collection<TargetProcess> procsBefore = fetchProcesses(container);
|
||||
procListener.putAll(container.getCachedElements());
|
||||
assertNull(getProcessRunning(procsBefore, specimen, this));
|
||||
runTestAttachByPid(attacher);
|
||||
retryVoid(() -> {
|
||||
// Cannot fetch elements. rely only on listener.
|
||||
assertNotNull(getProcessRunning(procListener.elements.values(), specimen, this));
|
||||
}, List.of(AssertionError.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAttachShowsInProcessContainerViaListener() throws Throwable {
|
||||
DebuggerTestSpecimen specimen = getAttachSpecimen();
|
||||
assumeTrue(m.hasProcessContainer());
|
||||
m.build();
|
||||
dummy = specimen.runDummy();
|
||||
|
||||
TargetAttacher attacher = findAttacher();
|
||||
TargetObject container = findProcessContainer();
|
||||
runTestAttachShowsInProcessContainerViaListener(attacher, container);
|
||||
runTestAttachShowsInProcessContainer(attacher);
|
||||
}
|
||||
}
|
||||
|
||||
+12
-13
@@ -16,7 +16,8 @@
|
||||
package ghidra.dbg.test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assume.*;
|
||||
import static org.junit.Assume.assumeNotNull;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
@@ -38,18 +39,16 @@ import ghidra.util.Msg;
|
||||
* Tests the functionality of breakpoints
|
||||
*
|
||||
* <p>
|
||||
* Note that this test does not check for nuances regarding specification vs.
|
||||
* location, as it is meant to generalize across models for interests of the UI
|
||||
* only. As such, we only test that we can set breakpoints at given addresses
|
||||
* and that a location manifests there, regardless of the intervening
|
||||
* mechanisms. We also test some basic operations on the breakpoint (location)
|
||||
* itself. Models which have separate specifications from locations, or for
|
||||
* which you want to test non-address specifications will need to add their own
|
||||
* tests, tailored to the semantics of that model's breakpoint specifications.
|
||||
* Note that this test does not check for nuances regarding specification vs. location, as it is
|
||||
* meant to generalize across models for interests of the UI only. As such, we only test that we can
|
||||
* set breakpoints at given addresses and that a location manifests there, regardless of the
|
||||
* intervening mechanisms. We also test some basic operations on the breakpoint (location) itself.
|
||||
* Models which have separate specifications from locations, or for which you want to test
|
||||
* non-address specifications will need to add their own tests, tailored to the semantics of that
|
||||
* model's breakpoint specifications.
|
||||
*
|
||||
* <p>
|
||||
* TODO: Enable, disable (if supported), delete (if supported), manipulation via
|
||||
* CLI is synced
|
||||
* TODO: Enable, disable (if supported), delete (if supported), manipulation via CLI is synced
|
||||
*/
|
||||
public abstract class AbstractDebuggerModelBreakpointsTest extends AbstractDebuggerModelTest
|
||||
implements RequiresTarget {
|
||||
@@ -225,7 +224,7 @@ public abstract class AbstractDebuggerModelBreakpointsTest extends AbstractDebug
|
||||
waitOn(container.placeBreakpoint(range, Set.of(kind)));
|
||||
retryVoid(() -> {
|
||||
Collection<? extends TargetBreakpointLocation> found =
|
||||
m.findAll(TargetBreakpointLocation.class, target.getPath()).values();
|
||||
m.findAll(TargetBreakpointLocation.class, target.getPath(), true).values();
|
||||
assertAtLeastOneLocCovers(found, range, kind);
|
||||
}, List.of(AssertionError.class));
|
||||
}
|
||||
@@ -261,7 +260,7 @@ public abstract class AbstractDebuggerModelBreakpointsTest extends AbstractDebug
|
||||
waitOn(container.placeBreakpoint(range, Set.of(kind)));
|
||||
locs.add(retry(() -> {
|
||||
Collection<? extends TargetBreakpointLocation> found =
|
||||
m.findAll(TargetBreakpointLocation.class, target.getPath()).values();
|
||||
m.findAll(TargetBreakpointLocation.class, target.getPath(), true).values();
|
||||
return assertAtLeastOneLocCovers(found, range, kind);
|
||||
}, List.of(AssertionError.class)));
|
||||
}
|
||||
|
||||
+4
@@ -27,6 +27,10 @@ import ghidra.dbg.target.TargetFocusScope;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
|
||||
/**
|
||||
* TODO: Since activation and focus are separate concepts, we need to fix the terminology here and
|
||||
* ensure we're testing the right things.
|
||||
*/
|
||||
public abstract class AbstractDebuggerModelFocusTest extends AbstractDebuggerModelTest {
|
||||
|
||||
/**
|
||||
|
||||
+80
-18
@@ -15,9 +15,10 @@
|
||||
*/
|
||||
package ghidra.dbg.test;
|
||||
|
||||
import static ghidra.lifecycle.Unfinished.*;
|
||||
import static ghidra.lifecycle.Unfinished.TODO;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assume.*;
|
||||
import static org.junit.Assume.assumeNotNull;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -27,23 +28,39 @@ import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import ghidra.async.AsyncReference;
|
||||
import ghidra.dbg.DebugModelConventions;
|
||||
import ghidra.dbg.DebuggerModelListener;
|
||||
import ghidra.dbg.error.DebuggerModelTerminatingException;
|
||||
import ghidra.dbg.target.*;
|
||||
import ghidra.dbg.target.TargetConsole.Channel;
|
||||
import ghidra.dbg.target.TargetInterpreter;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.testutil.CatchOffThread;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
public abstract class AbstractDebuggerModelInterpreterTest extends AbstractDebuggerModelTest
|
||||
implements RequiresAttachSpecimen, RequiresLaunchSpecimen {
|
||||
|
||||
/**
|
||||
* Get the path of the expected result of {@link #findInterpreter()} for this test
|
||||
*
|
||||
* @return the expected path
|
||||
*/
|
||||
public List<String> getExpectedInterpreterPath() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the CLI command to echo a string back
|
||||
*
|
||||
* @param msg the message to echo
|
||||
* @return the command
|
||||
*/
|
||||
protected abstract String getEchoCommand(String msg);
|
||||
|
||||
/**
|
||||
* If applicable, get the CLI command to terminate the session / model
|
||||
*
|
||||
* @return the command
|
||||
*/
|
||||
protected abstract String getQuitCommand();
|
||||
|
||||
/**
|
||||
@@ -53,6 +70,30 @@ public abstract class AbstractDebuggerModelInterpreterTest extends AbstractDebug
|
||||
*/
|
||||
protected abstract String getAttachCommand();
|
||||
|
||||
/**
|
||||
* Get the CLI command to detach from the given process
|
||||
*
|
||||
* <p>
|
||||
* Note that the given process should already be the current/active process of the interpreter,
|
||||
* so the parameter may not be needed.
|
||||
*
|
||||
* @param process the process to detach from, which should already be active
|
||||
* @return the command
|
||||
*/
|
||||
protected abstract String getDetachCommand(TargetProcess process);
|
||||
|
||||
/**
|
||||
* Get the CLI command to kill the given process
|
||||
*
|
||||
* <p>
|
||||
* Note that the given process should already be the current/active process of the interpreter,
|
||||
* so the parameter may not be needed.
|
||||
*
|
||||
* @param process the process to kill, which should already be active
|
||||
* @return the command
|
||||
*/
|
||||
protected abstract String getKillCommand(TargetProcess process);
|
||||
|
||||
@Test
|
||||
public void testInterpreterIsWhereExpected() throws Throwable {
|
||||
List<String> expectedInterpreterPath = getExpectedInterpreterPath();
|
||||
@@ -126,6 +167,11 @@ public abstract class AbstractDebuggerModelInterpreterTest extends AbstractDebug
|
||||
runTestExecuteCapture(interpreter, cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the user quitting via the CLI properly terminates the model
|
||||
*
|
||||
* @throws Throwable expected since the model will terminate
|
||||
*/
|
||||
@Test(expected = DebuggerModelTerminatingException.class)
|
||||
public void testExecuteQuit() throws Throwable {
|
||||
String cmd = getQuitCommand();
|
||||
@@ -151,14 +197,22 @@ public abstract class AbstractDebuggerModelInterpreterTest extends AbstractDebug
|
||||
// TODO: Delete (spec vs. loc?)
|
||||
}
|
||||
|
||||
protected void runTestLaunchViaInterpreterShowsInProcessContainer(TargetInterpreter interpreter,
|
||||
TargetObject container) throws Throwable {
|
||||
protected TargetProcess runTestLaunchViaInterpreterShowsInProcessContainer(
|
||||
TargetInterpreter interpreter) throws Throwable {
|
||||
DebuggerTestSpecimen specimen = getLaunchSpecimen();
|
||||
assertNull(getProcessRunning(container, specimen, this));
|
||||
assertNull(getProcessRunning(specimen, this));
|
||||
for (String line : specimen.getLaunchScript()) {
|
||||
waitOn(interpreter.execute(line));
|
||||
}
|
||||
retryForProcessRunning(container, specimen, this);
|
||||
return retryForProcessRunning(specimen, this);
|
||||
}
|
||||
|
||||
protected void runTestKillViaInterpreter(TargetProcess process, TargetInterpreter interpreter)
|
||||
throws Throwable {
|
||||
waitOn(interpreter.execute(getKillCommand(process)));
|
||||
retryVoid(() -> {
|
||||
assertFalse(DebugModelConventions.isProcessAlive(process));
|
||||
}, List.of(AssertionError.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -167,18 +221,26 @@ public abstract class AbstractDebuggerModelInterpreterTest extends AbstractDebug
|
||||
m.build();
|
||||
|
||||
TargetInterpreter interpreter = findInterpreter();
|
||||
TargetObject container = findProcessContainer();
|
||||
assertNotNull("No process container", container);
|
||||
runTestLaunchViaInterpreterShowsInProcessContainer(interpreter, container);
|
||||
TargetProcess process = runTestLaunchViaInterpreterShowsInProcessContainer(interpreter);
|
||||
|
||||
runTestKillViaInterpreter(process, interpreter);
|
||||
}
|
||||
|
||||
protected void runTestAttachViaInterpreterShowsInProcessContainer(TargetInterpreter interpreter,
|
||||
TargetObject container) throws Throwable {
|
||||
protected TargetProcess runTestAttachViaInterpreterShowsInProcessContainer(
|
||||
TargetInterpreter interpreter) throws Throwable {
|
||||
DebuggerTestSpecimen specimen = getAttachSpecimen();
|
||||
assertNull(getProcessRunning(container, specimen, this));
|
||||
assertNull(getProcessRunning(specimen, this));
|
||||
String cmd = getAttachCommand();
|
||||
waitOn(interpreter.execute(cmd));
|
||||
retryForProcessRunning(container, specimen, this);
|
||||
return retryForProcessRunning(specimen, this);
|
||||
}
|
||||
|
||||
protected void runTestDetachViaInterpreter(TargetProcess process, TargetInterpreter interpreter)
|
||||
throws Throwable {
|
||||
waitOn(interpreter.execute(getDetachCommand(process)));
|
||||
retryVoid(() -> {
|
||||
assertFalse(DebugModelConventions.isProcessAlive(process));
|
||||
}, List.of(AssertionError.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -189,8 +251,8 @@ public abstract class AbstractDebuggerModelInterpreterTest extends AbstractDebug
|
||||
dummy = specimen.runDummy();
|
||||
|
||||
TargetInterpreter interpreter = findInterpreter();
|
||||
TargetObject container = findProcessContainer();
|
||||
assertNotNull("No process container", container);
|
||||
runTestAttachViaInterpreterShowsInProcessContainer(interpreter, container);
|
||||
TargetProcess process = runTestAttachViaInterpreterShowsInProcessContainer(interpreter);
|
||||
|
||||
runTestDetachViaInterpreter(process, interpreter);
|
||||
}
|
||||
}
|
||||
|
||||
+18
-68
@@ -15,12 +15,12 @@
|
||||
*/
|
||||
package ghidra.dbg.test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assume.assumeNotNull;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@@ -31,7 +31,6 @@ import ghidra.dbg.DebugModelConventions;
|
||||
import ghidra.dbg.target.*;
|
||||
import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState;
|
||||
import ghidra.dbg.target.TargetMethod.TargetParameterMap;
|
||||
import ghidra.dbg.testutil.ElementTrackingListener;
|
||||
|
||||
public abstract class AbstractDebuggerModelLauncherTest extends AbstractDebuggerModelTest
|
||||
implements RequiresLaunchSpecimen {
|
||||
@@ -40,10 +39,6 @@ public abstract class AbstractDebuggerModelLauncherTest extends AbstractDebugger
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<String> getExpectedProcessesContainerPath() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract TargetParameterMap getExpectedLauncherParameters();
|
||||
|
||||
public abstract void assertEnvironment(TargetEnvironment environment);
|
||||
@@ -58,16 +53,6 @@ public abstract class AbstractDebuggerModelLauncherTest extends AbstractDebugger
|
||||
assertEquals(expectedLauncherPath, launcher.getPath());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessContainerIsWhereExpected() throws Throwable {
|
||||
List<String> expectedProcessContainerPath = getExpectedProcessesContainerPath();
|
||||
assumeNotNull(expectedProcessContainerPath);
|
||||
m.build();
|
||||
|
||||
TargetObject container = findProcessContainer();
|
||||
assertEquals(expectedProcessContainerPath, container.getPath());
|
||||
}
|
||||
|
||||
protected void runTestLaunchParameters(TargetLauncher launcher,
|
||||
TargetParameterMap expectedParameters) throws Throwable {
|
||||
waitAcc(launcher);
|
||||
@@ -123,12 +108,11 @@ public abstract class AbstractDebuggerModelLauncherTest extends AbstractDebugger
|
||||
waitOn(listener.observedCreated);
|
||||
}
|
||||
|
||||
protected void runTestLaunchThenDetach(TargetLauncher launcher,
|
||||
TargetObject container) throws Throwable {
|
||||
protected void runTestLaunchThenDetach(TargetLauncher launcher) throws Throwable {
|
||||
DebuggerTestSpecimen specimen = getLaunchSpecimen();
|
||||
assertNull(getProcessRunning(container, specimen, this));
|
||||
assertNull(getProcessRunning(specimen, this));
|
||||
runTestLaunch(launcher);
|
||||
runTestDetach(container, specimen);
|
||||
runTestDetach(specimen);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -137,16 +121,14 @@ public abstract class AbstractDebuggerModelLauncherTest extends AbstractDebugger
|
||||
m.build();
|
||||
|
||||
TargetLauncher launcher = findLauncher();
|
||||
TargetObject container = findProcessContainer();
|
||||
runTestLaunchThenDetach(launcher, container);
|
||||
runTestLaunchThenDetach(launcher);
|
||||
}
|
||||
|
||||
protected void runTestLaunchThenKill(TargetLauncher launcher,
|
||||
TargetObject container) throws Throwable {
|
||||
protected void runTestLaunchThenKill(TargetLauncher launcher) throws Throwable {
|
||||
DebuggerTestSpecimen specimen = getLaunchSpecimen();
|
||||
assertNull(getProcessRunning(container, specimen, this));
|
||||
assertNull(getProcessRunning(specimen, this));
|
||||
runTestLaunch(launcher);
|
||||
runTestKill(container, specimen);
|
||||
runTestKill(specimen);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -155,16 +137,14 @@ public abstract class AbstractDebuggerModelLauncherTest extends AbstractDebugger
|
||||
m.build();
|
||||
|
||||
TargetLauncher launcher = findLauncher();
|
||||
TargetObject container = findProcessContainer();
|
||||
runTestLaunchThenKill(launcher, container);
|
||||
runTestLaunchThenKill(launcher);
|
||||
}
|
||||
|
||||
protected void runTestLaunchThenResume(TargetLauncher launcher,
|
||||
TargetObject container) throws Throwable {
|
||||
protected void runTestLaunchThenResume(TargetLauncher launcher) throws Throwable {
|
||||
DebuggerTestSpecimen specimen = getLaunchSpecimen();
|
||||
assertNull(getProcessRunning(container, specimen, this));
|
||||
assertNull(getProcessRunning(specimen, this));
|
||||
runTestLaunch(launcher);
|
||||
runTestResumeTerminates(container, specimen);
|
||||
runTestResumeTerminates(specimen);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -173,16 +153,14 @@ public abstract class AbstractDebuggerModelLauncherTest extends AbstractDebugger
|
||||
m.build();
|
||||
|
||||
TargetLauncher launcher = findLauncher();
|
||||
TargetObject container = findProcessContainer();
|
||||
runTestLaunchThenResume(launcher, container);
|
||||
runTestLaunchThenResume(launcher);
|
||||
}
|
||||
|
||||
protected void runTestLaunchShowsInProcessContainer(TargetLauncher launcher,
|
||||
TargetObject container) throws Throwable {
|
||||
protected void runTestLaunchShowsInProcessContainer(TargetLauncher launcher) throws Throwable {
|
||||
DebuggerTestSpecimen specimen = getLaunchSpecimen();
|
||||
assertNull(getProcessRunning(container, specimen, this));
|
||||
assertNull(getProcessRunning(specimen, this));
|
||||
runTestLaunch(launcher);
|
||||
retryForProcessRunning(container, specimen, this);
|
||||
retryForProcessRunning(specimen, this);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -191,34 +169,6 @@ public abstract class AbstractDebuggerModelLauncherTest extends AbstractDebugger
|
||||
m.build();
|
||||
|
||||
TargetLauncher launcher = findLauncher();
|
||||
TargetObject container = findProcessContainer();
|
||||
runTestLaunchShowsInProcessContainer(launcher, container);
|
||||
}
|
||||
|
||||
protected void runTestLaunchShowsInProcessContainerViaListener(
|
||||
TargetLauncher launcher, TargetObject container) throws Throwable {
|
||||
DebuggerTestSpecimen specimen = getLaunchSpecimen();
|
||||
ElementTrackingListener<? extends TargetProcess> procListener =
|
||||
new ElementTrackingListener<>(TargetProcess.class);
|
||||
container.addListener(procListener);
|
||||
// NB. Have to express interest, otherwise model is not obligated to invoke listener
|
||||
Collection<TargetProcess> procsBefore = fetchProcesses(container);
|
||||
procListener.putAll(container.getCachedElements());
|
||||
assertNull(getProcessRunning(procsBefore, specimen, this));
|
||||
runTestLaunch(launcher);
|
||||
retryVoid(() -> {
|
||||
// Cannot fetch elements. rely only on listener.
|
||||
assertNotNull(getProcessRunning(procListener.elements.values(), specimen, this));
|
||||
}, List.of(AssertionError.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLaunchShowsInProcessContainerViaListener() throws Throwable {
|
||||
assumeTrue(m.hasProcessContainer());
|
||||
m.build();
|
||||
|
||||
TargetLauncher launcher = findLauncher();
|
||||
TargetObject container = findProcessContainer();
|
||||
runTestLaunchShowsInProcessContainerViaListener(launcher, container);
|
||||
runTestLaunchShowsInProcessContainer(launcher);
|
||||
}
|
||||
}
|
||||
|
||||
+5
-6
@@ -15,7 +15,8 @@
|
||||
*/
|
||||
package ghidra.dbg.test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.*;
|
||||
@@ -131,14 +132,12 @@ public abstract class AbstractDebuggerModelScenarioCloneExitTest extends Abstrac
|
||||
Msg.debug(this, "Launching " + specimen);
|
||||
waitOn(launcher.launch(specimen.getLauncherArgs()));
|
||||
Msg.debug(this, " Done launching");
|
||||
TargetObject processContainer = findProcessContainer();
|
||||
assertNotNull("No process container", processContainer);
|
||||
TargetProcess process = retryForProcessRunning(processContainer, specimen, this);
|
||||
TargetProcess process = retryForProcessRunning(specimen, this);
|
||||
postLaunch(process);
|
||||
TargetBreakpointSpecContainer breakpointContainer =
|
||||
TargetBreakpointSpecContainer bpContainer =
|
||||
findBreakpointSpecContainer(process.getPath());
|
||||
Msg.debug(this, "Placing breakpoint");
|
||||
waitOn(breakpointContainer.placeBreakpoint(getBreakpointExpression(),
|
||||
waitOn(bpContainer.placeBreakpoint(getBreakpointExpression(),
|
||||
Set.of(TargetBreakpointKind.SW_EXECUTE)));
|
||||
|
||||
assertTrue(DebugModelConventions.isProcessAlive(process));
|
||||
|
||||
+1
-3
@@ -182,8 +182,6 @@ public abstract class AbstractDebuggerModelScenarioForkExitTest extends Abstract
|
||||
Msg.debug(this, "Launching " + specimen);
|
||||
waitOn(launcher.launch(specimen.getLauncherArgs()));
|
||||
Msg.debug(this, " Done launching");
|
||||
TargetObject processContainer = findProcessContainer();
|
||||
assertNotNull("No process container", processContainer);
|
||||
TargetProcess parentProcess = waitOn(stateMonitor.observedParent);
|
||||
Msg.debug(this, "Parent is " + parentProcess.getJoinedPath("."));
|
||||
postLaunch(parentProcess);
|
||||
@@ -201,7 +199,7 @@ public abstract class AbstractDebuggerModelScenarioForkExitTest extends Abstract
|
||||
Msg.debug(this, " Done " + i);
|
||||
waitAcc(access(parentProcess));
|
||||
try {
|
||||
childProcess = retryForOtherProcessRunning(processContainer, specimen, this,
|
||||
childProcess = retryForOtherProcessRunning(specimen, this,
|
||||
p -> p != parentProcess, WAIT_FOR_CHILD_MS);
|
||||
}
|
||||
catch (AssertionError e) {
|
||||
|
||||
+1
-2
@@ -141,8 +141,7 @@ public abstract class AbstractDebuggerModelScenarioMemoryTest extends AbstractDe
|
||||
Msg.debug(this, "Launching " + specimen);
|
||||
waitOn(launcher.launch(specimen.getLauncherArgs()));
|
||||
Msg.debug(this, " Done launching");
|
||||
TargetObject processContainer = findProcessContainer();
|
||||
TargetProcess process = retryForProcessRunning(processContainer, specimen, this);
|
||||
TargetProcess process = retryForProcessRunning(specimen, this);
|
||||
postLaunch(process);
|
||||
|
||||
Address address = Objects.requireNonNull(getAddressToWrite(process));
|
||||
|
||||
+1
-4
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package ghidra.dbg.test;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
@@ -138,9 +137,7 @@ public abstract class AbstractDebuggerModelScenarioRegistersTest extends Abstrac
|
||||
Msg.debug(this, "Launching " + specimen);
|
||||
waitOn(launcher.launch(specimen.getLauncherArgs()));
|
||||
Msg.debug(this, " Done launching");
|
||||
TargetObject processContainer = findProcessContainer();
|
||||
assertNotNull(processContainer);
|
||||
TargetProcess process = retryForProcessRunning(processContainer, specimen, this);
|
||||
TargetProcess process = retryForProcessRunning(specimen, this);
|
||||
postLaunch(process);
|
||||
|
||||
TargetBreakpointSpecContainer breakpointContainer =
|
||||
|
||||
+2
-3
@@ -122,8 +122,7 @@ public abstract class AbstractDebuggerModelScenarioStackTest extends AbstractDeb
|
||||
TargetLauncher launcher = findLauncher();
|
||||
waitOn(launcher.launch(specimen.getLauncherArgs()));
|
||||
Msg.debug(this, " Done launching");
|
||||
TargetObject processContainer = findProcessContainer();
|
||||
TargetProcess process = retryForProcessRunning(processContainer, specimen, this);
|
||||
TargetProcess process = retryForProcessRunning(specimen, this);
|
||||
postLaunch(process);
|
||||
|
||||
TargetBreakpointSpecContainer breakpointContainer =
|
||||
@@ -157,7 +156,7 @@ public abstract class AbstractDebuggerModelScenarioStackTest extends AbstractDeb
|
||||
// Sort by path should present them innermost to outermost
|
||||
List<TargetStackFrame> frames = retry(() -> {
|
||||
List<TargetStackFrame> result =
|
||||
List.copyOf(m.findAll(TargetStackFrame.class, stack.getPath()).values());
|
||||
List.copyOf(m.findAll(TargetStackFrame.class, stack.getPath(), true).values());
|
||||
assertTrue("Fewer than 4 frames", result.size() > 4);
|
||||
return result;
|
||||
}, List.of(AssertionError.class));
|
||||
|
||||
+9
-23
@@ -85,19 +85,6 @@ public abstract class AbstractDebuggerModelTest extends AbstractGhidraHeadlessIn
|
||||
return m.find(TargetLauncher.class, seedPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the process container under test
|
||||
*
|
||||
* <p>
|
||||
* This can be overridden to force a different object under the test.
|
||||
*
|
||||
* @return the process container
|
||||
* @throws Throwable if anything goes wrong
|
||||
*/
|
||||
protected TargetObject findProcessContainer() throws Throwable {
|
||||
return m.findContainer(TargetProcess.class, seedPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the breakpoint container of a target under test
|
||||
*
|
||||
@@ -285,9 +272,9 @@ public abstract class AbstractDebuggerModelTest extends AbstractGhidraHeadlessIn
|
||||
return waitOn(listener.trapped);
|
||||
}
|
||||
|
||||
protected void runTestDetach(TargetObject container, DebuggerTestSpecimen specimen)
|
||||
protected void runTestDetach(DebuggerTestSpecimen specimen)
|
||||
throws Throwable {
|
||||
TargetProcess process = retryForProcessRunning(container, specimen, this);
|
||||
TargetProcess process = retryForProcessRunning(specimen, this);
|
||||
TargetDetachable detachable = m.suitable(TargetDetachable.class, process.getPath());
|
||||
waitAcc(detachable);
|
||||
waitOn(detachable.detach());
|
||||
@@ -295,9 +282,9 @@ public abstract class AbstractDebuggerModelTest extends AbstractGhidraHeadlessIn
|
||||
List.of(AssertionError.class));
|
||||
}
|
||||
|
||||
protected void runTestKill(TargetObject container, DebuggerTestSpecimen specimen)
|
||||
protected void runTestKill(DebuggerTestSpecimen specimen)
|
||||
throws Throwable {
|
||||
TargetProcess process = retryForProcessRunning(container, specimen, this);
|
||||
TargetProcess process = retryForProcessRunning(specimen, this);
|
||||
TargetKillable killable = m.suitable(TargetKillable.class, process.getPath());
|
||||
waitAcc(killable);
|
||||
waitOn(killable.kill());
|
||||
@@ -305,9 +292,8 @@ public abstract class AbstractDebuggerModelTest extends AbstractGhidraHeadlessIn
|
||||
List.of(AssertionError.class));
|
||||
}
|
||||
|
||||
protected void runTestResumeTerminates(TargetObject container, DebuggerTestSpecimen specimen)
|
||||
throws Throwable {
|
||||
TargetProcess process = retryForProcessRunning(container, specimen, this);
|
||||
protected void runTestResumeTerminates(DebuggerTestSpecimen specimen) throws Throwable {
|
||||
TargetProcess process = retryForProcessRunning(specimen, this);
|
||||
TargetResumable resumable = m.suitable(TargetResumable.class, process.getPath());
|
||||
AsyncState state =
|
||||
new AsyncState(m.suitable(TargetExecutionStateful.class, process.getPath()));
|
||||
@@ -318,9 +304,9 @@ public abstract class AbstractDebuggerModelTest extends AbstractGhidraHeadlessIn
|
||||
List.of(AssertionError.class));
|
||||
}
|
||||
|
||||
protected void runTestResumeInterruptMany(TargetObject container, DebuggerTestSpecimen specimen,
|
||||
protected void runTestResumeInterruptMany(DebuggerTestSpecimen specimen,
|
||||
int repetitions) throws Throwable {
|
||||
TargetProcess process = retryForProcessRunning(container, specimen, this);
|
||||
TargetProcess process = retryForProcessRunning(specimen, this);
|
||||
TargetResumable resumable = m.suitable(TargetResumable.class, process.getPath());
|
||||
TargetInterruptible interruptible =
|
||||
m.suitable(TargetInterruptible.class, process.getPath());
|
||||
@@ -342,6 +328,6 @@ public abstract class AbstractDebuggerModelTest extends AbstractGhidraHeadlessIn
|
||||
}, List.of(AssertionError.class));
|
||||
}
|
||||
}
|
||||
waitOn(container.getModel().ping("Are you still there?"));
|
||||
waitOn(m.getModel().ping("Are you still there?"));
|
||||
}
|
||||
}
|
||||
|
||||
+6
-2
@@ -206,16 +206,20 @@ public abstract class AbstractModelHost implements ModelHost, DebuggerModelTestU
|
||||
|
||||
@Override
|
||||
public <T extends TargetObject> NavigableMap<List<String>, T> findAll(Class<T> cls,
|
||||
List<String> seedPath) throws Throwable {
|
||||
List<String> seedPath, boolean atLeastOne) throws Throwable {
|
||||
PathMatcher matcher =
|
||||
model.getRootSchema().getSuccessorSchema(seedPath).searchFor(cls, seedPath, false);
|
||||
if (matcher.isEmpty()) {
|
||||
return new TreeMap<>();
|
||||
}
|
||||
|
||||
NavigableMap<List<String>, ?> found = atLeastOne
|
||||
? waitOn(waiter.waitAtLeastOne(matcher))
|
||||
: matcher.getCachedValues(model.getModelRoot());
|
||||
// NB. Outside of testing, an "unsafe" cast of the map should be fine.
|
||||
// During testing, we should expend the energy to verify the heap.
|
||||
NavigableMap<List<String>, T> result = new TreeMap<>(PathComparator.KEYED);
|
||||
for (Entry<List<String>, ?> ent : waitOn(waiter.waitAtLeastOne(matcher)).entrySet()) {
|
||||
for (Entry<List<String>, ?> ent : found.entrySet()) {
|
||||
result.put(ent.getKey(), cls.cast(ent.getValue()));
|
||||
}
|
||||
return result;
|
||||
|
||||
+1
-2
@@ -29,12 +29,11 @@ public interface ProvidesTargetViaAttachSpecimen extends RequiresTarget, Require
|
||||
@Override
|
||||
default TargetObject obtainTarget() throws Throwable {
|
||||
TargetAttacher attacher = getTest().findAttacher();
|
||||
TargetObject container = getTest().findProcessContainer();
|
||||
DebuggerTestSpecimen specimen = getAttachSpecimen();
|
||||
waitAcc(attacher);
|
||||
DummyProc dummy = specimen.runDummy();
|
||||
setDummy(dummy);
|
||||
attacher.attach(dummy.pid);
|
||||
return retryForProcessRunning(container, specimen, getTest());
|
||||
return retryForProcessRunning(specimen, getTest());
|
||||
}
|
||||
}
|
||||
|
||||
+2
-4
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package ghidra.dbg.test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import ghidra.dbg.target.TargetLauncher;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
@@ -34,11 +34,9 @@ public interface ProvidesTargetViaLaunchSpecimen extends RequiresTarget, Require
|
||||
default TargetObject obtainTarget() throws Throwable {
|
||||
TargetLauncher launcher = getTest().findLauncher();
|
||||
assertNotNull("No launcher found", launcher);
|
||||
TargetObject container = getTest().findProcessContainer();
|
||||
assertNotNull("No process container found", container);
|
||||
DebuggerTestSpecimen specimen = getLaunchSpecimen();
|
||||
waitAcc(launcher);
|
||||
launcher.launch(specimen.getLauncherArgs());
|
||||
return retryForProcessRunning(container, specimen, getTest());
|
||||
return retryForProcessRunning(specimen, getTest());
|
||||
}
|
||||
}
|
||||
|
||||
+14
-16
@@ -31,6 +31,7 @@ import ghidra.dbg.target.*;
|
||||
import ghidra.dbg.target.TargetSteppable.TargetStepKind;
|
||||
import ghidra.dbg.test.AbstractDebuggerModelTest;
|
||||
import ghidra.dbg.test.AbstractDebuggerModelTest.DebuggerTestSpecimen;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
import ghidra.util.NumericUtilities;
|
||||
|
||||
public interface DebuggerModelTestUtils extends AsyncTestUtils {
|
||||
@@ -164,10 +165,9 @@ public interface DebuggerModelTestUtils extends AsyncTestUtils {
|
||||
}).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
default Collection<TargetProcess> fetchProcesses(TargetObject container)
|
||||
default Collection<TargetProcess> fetchProcesses(AbstractDebuggerModelTest test)
|
||||
throws Throwable {
|
||||
return (Collection) waitOn(container.fetchElements(true)).values();
|
||||
return test.m.findAll(TargetProcess.class, PathUtils.parse(""), false).values();
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@@ -176,32 +176,30 @@ public interface DebuggerModelTestUtils extends AsyncTestUtils {
|
||||
return (Collection) waitOn(container.fetchElements(true)).values();
|
||||
}
|
||||
|
||||
default TargetProcess getProcessRunning(TargetObject container,
|
||||
DebuggerTestSpecimen specimen, AbstractDebuggerModelTest test) throws Throwable {
|
||||
return getProcessRunning(container, specimen, test, p -> true);
|
||||
default TargetProcess getProcessRunning(DebuggerTestSpecimen specimen,
|
||||
AbstractDebuggerModelTest test) throws Throwable {
|
||||
return getProcessRunning(specimen, test, p -> true);
|
||||
}
|
||||
|
||||
default TargetProcess getProcessRunning(TargetObject container,
|
||||
DebuggerTestSpecimen specimen, AbstractDebuggerModelTest test,
|
||||
Predicate<TargetProcess> predicate) throws Throwable {
|
||||
return getProcessRunning(fetchProcesses(container), specimen, test, predicate);
|
||||
default TargetProcess getProcessRunning(DebuggerTestSpecimen specimen,
|
||||
AbstractDebuggerModelTest test, Predicate<TargetProcess> predicate) throws Throwable {
|
||||
return getProcessRunning(fetchProcesses(test), specimen, test, predicate);
|
||||
}
|
||||
|
||||
default TargetProcess retryForProcessRunning(TargetObject container,
|
||||
default TargetProcess retryForProcessRunning(
|
||||
DebuggerTestSpecimen specimen, AbstractDebuggerModelTest test) throws Throwable {
|
||||
return retry(() -> {
|
||||
TargetProcess process = getProcessRunning(container, specimen, test);
|
||||
TargetProcess process = getProcessRunning(specimen, test);
|
||||
assertNotNull(process);
|
||||
return process;
|
||||
}, List.of(AssertionError.class));
|
||||
}
|
||||
|
||||
default TargetProcess retryForOtherProcessRunning(TargetObject container,
|
||||
DebuggerTestSpecimen specimen, AbstractDebuggerModelTest test,
|
||||
Predicate<TargetProcess> predicate, long timeoutMs)
|
||||
default TargetProcess retryForOtherProcessRunning(DebuggerTestSpecimen specimen,
|
||||
AbstractDebuggerModelTest test, Predicate<TargetProcess> predicate, long timeoutMs)
|
||||
throws Throwable {
|
||||
return retry(timeoutMs, () -> {
|
||||
TargetProcess process = getProcessRunning(container, specimen, test, predicate);
|
||||
TargetProcess process = getProcessRunning(specimen, test, predicate);
|
||||
assertNotNull(process);
|
||||
return process;
|
||||
}, List.of(AssertionError.class));
|
||||
|
||||
+2
-2
@@ -73,8 +73,8 @@ public interface TestDebuggerModelProvider {
|
||||
|
||||
<T extends TargetObject> T findAny(Class<T> cls, List<String> seedPath) throws Throwable;
|
||||
|
||||
<T extends TargetObject> Map<List<String>, T> findAll(Class<T> cls, List<String> seedPath)
|
||||
throws Throwable;
|
||||
<T extends TargetObject> Map<List<String>, T> findAll(Class<T> cls, List<String> seedPath,
|
||||
boolean atLeastOne) throws Throwable;
|
||||
|
||||
TargetObject findContainer(Class<? extends TargetObject> cls, List<String> seedPath)
|
||||
throws Throwable;
|
||||
|
||||
Reference in New Issue
Block a user