mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-22 20:22:44 +00:00
GP-903: Moved "recovery data" and "upgrade" program prompts to debugger console.
This commit is contained in:
parent
ca66feec30
commit
813dff60f0
@ -986,13 +986,29 @@ public interface DebuggerResources {
|
||||
|
||||
static ActionBuilder builder(Plugin owner) {
|
||||
String ownerName = owner.getName();
|
||||
return new ActionBuilder(NAME, ownerName).description(DESCRIPTION)
|
||||
return new ActionBuilder(NAME, ownerName)
|
||||
.description(DESCRIPTION)
|
||||
.menuGroup(GROUP)
|
||||
.menuPath(NAME)
|
||||
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
|
||||
}
|
||||
}
|
||||
|
||||
interface OpenProgramAction {
|
||||
String NAME = "Open Program";
|
||||
Icon ICON = ICON_PROGRAM;
|
||||
String DESCRIPTION = "Open the program";
|
||||
String HELP_ANCHOR = "open_program";
|
||||
|
||||
static ActionBuilder builder(Plugin owner) {
|
||||
String ownerName = owner.getName();
|
||||
return new ActionBuilder(NAME, ownerName)
|
||||
.description(DESCRIPTION)
|
||||
.toolBarIcon(ICON)
|
||||
.helpLocation(new HelpLocation(ownerName, HELP_ANCHOR));
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AbstractToggleBreakpointAction extends DockingAction {
|
||||
public static final String NAME = "Toggle Breakpoint";
|
||||
// TODO: A "toggle breakpoint" icon
|
||||
|
@ -29,6 +29,7 @@ import docking.ActionContext;
|
||||
import docking.action.DockingActionIf;
|
||||
import ghidra.app.plugin.PluginCategoryNames;
|
||||
import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
|
||||
import ghidra.app.plugin.core.debug.gui.console.DebuggerConsoleProvider.LogRow;
|
||||
import ghidra.app.services.DebuggerConsoleService;
|
||||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.util.PluginStatus;
|
||||
@ -105,8 +106,13 @@ public class DebuggerConsolePlugin extends Plugin implements DebuggerConsoleServ
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(ActionContext context) {
|
||||
provider.remove(context);
|
||||
public void removeFromLog(ActionContext context) {
|
||||
provider.removeFromLog(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean logContains(ActionContext context) {
|
||||
return provider.logContains(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -127,4 +133,14 @@ public class DebuggerConsolePlugin extends Plugin implements DebuggerConsoleServ
|
||||
public long getRowCount(Class<? extends ActionContext> ctxCls) {
|
||||
return provider.getRowCount(ctxCls);
|
||||
}
|
||||
|
||||
/**
|
||||
* For testing: to verify the contents of a message delivered to the console log
|
||||
*
|
||||
* @param ctx the context
|
||||
* @return the the log entry
|
||||
*/
|
||||
public LogRow getLogRow(ActionContext ctx) {
|
||||
return provider.getLogRow(ctx);
|
||||
}
|
||||
}
|
||||
|
@ -109,9 +109,15 @@ public class DebuggerConsoleProvider extends ComponentProviderAdapter
|
||||
}
|
||||
}
|
||||
|
||||
protected static class BoundAction {
|
||||
protected final DockingActionIf action;
|
||||
protected final ActionContext context;
|
||||
/**
|
||||
* An action bound to a context
|
||||
*
|
||||
* <p>
|
||||
* This class is public for access by test cases only.
|
||||
*/
|
||||
public static class BoundAction {
|
||||
public final DockingActionIf action;
|
||||
public final ActionContext context;
|
||||
|
||||
public BoundAction(DockingActionIf action, ActionContext context) {
|
||||
this.action = action;
|
||||
@ -144,10 +150,22 @@ public class DebuggerConsoleProvider extends ComponentProviderAdapter
|
||||
}
|
||||
}
|
||||
|
||||
protected static class ActionList extends ArrayList<BoundAction> {
|
||||
/**
|
||||
* A list of bound actions
|
||||
*
|
||||
* <p>
|
||||
* This class is public for access by test cases only.
|
||||
*/
|
||||
public static class ActionList extends ArrayList<BoundAction> {
|
||||
}
|
||||
|
||||
protected static class LogRow {
|
||||
/**
|
||||
* An entry in the console's log
|
||||
*
|
||||
* <p>
|
||||
* This class is public for access by test cases only.
|
||||
*/
|
||||
public static class LogRow {
|
||||
private final Icon icon;
|
||||
private final String message;
|
||||
private final Date date;
|
||||
@ -419,13 +437,19 @@ public class DebuggerConsoleProvider extends ComponentProviderAdapter
|
||||
new Date(event.getTimeMillis()), context, computeToolbarActions(context)));
|
||||
}
|
||||
|
||||
protected void remove(ActionContext context) {
|
||||
protected void removeFromLog(ActionContext context) {
|
||||
synchronized (buffer) {
|
||||
LogRow r = logTableModel.deleteKey(context);
|
||||
buffer.remove(r);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean logContains(ActionContext context) {
|
||||
synchronized (buffer) {
|
||||
return logTableModel.getMap().containsKey(context);
|
||||
}
|
||||
}
|
||||
|
||||
protected void addResolutionAction(DockingActionIf action) {
|
||||
DockingActionIf replaced =
|
||||
actionsByOwnerThenName.computeIfAbsent(action.getOwner(), o -> new LinkedHashMap<>())
|
||||
@ -479,9 +503,17 @@ public class DebuggerConsoleProvider extends ComponentProviderAdapter
|
||||
}
|
||||
|
||||
protected long getRowCount(Class<? extends ActionContext> ctxCls) {
|
||||
return logTableModel.getModelData()
|
||||
.stream()
|
||||
.filter(r -> ctxCls.isInstance(r.context))
|
||||
.count();
|
||||
synchronized (buffer) {
|
||||
return logTableModel.getModelData()
|
||||
.stream()
|
||||
.filter(r -> ctxCls.isInstance(r.context))
|
||||
.count();
|
||||
}
|
||||
}
|
||||
|
||||
public LogRow getLogRow(ActionContext ctx) {
|
||||
synchronized (buffer) {
|
||||
return logTableModel.getMap().get(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ import utilities.util.SuppressableCallback.Suppression;
|
||||
eventsConsumed = {
|
||||
// ProgramSelectionPluginEvent.class, // TODO: Later or remove
|
||||
// ProgramHighlightPluginEvent.class, // TODO: Later or remove
|
||||
ProgramOpenedPluginEvent.class, // For auto-open log cleanup
|
||||
ProgramClosedPluginEvent.class, // For marker set cleanup
|
||||
ProgramLocationPluginEvent.class, // For static listing sync
|
||||
TraceActivatedPluginEvent.class, // Trace/thread activation and register tracking
|
||||
@ -275,6 +276,10 @@ public class DebuggerListingPlugin extends CodeBrowserPlugin implements Debugger
|
||||
}
|
||||
});
|
||||
}
|
||||
if (event instanceof ProgramOpenedPluginEvent) {
|
||||
ProgramOpenedPluginEvent ev = (ProgramOpenedPluginEvent) event;
|
||||
allProviders(p -> p.programOpened(ev.getProgram()));
|
||||
}
|
||||
if (event instanceof ProgramClosedPluginEvent) {
|
||||
ProgramClosedPluginEvent ev = (ProgramClosedPluginEvent) event;
|
||||
allProviders(p -> p.programClosed(ev.getProgram()));
|
||||
|
@ -85,6 +85,9 @@ import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.model.time.TraceSnapshot;
|
||||
import ghidra.trace.util.TraceAddressSpace;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.exception.VersionException;
|
||||
import ghidra.util.task.*;
|
||||
import utilities.util.SuppressableCallback;
|
||||
import utilities.util.SuppressableCallback.Suppression;
|
||||
|
||||
@ -352,6 +355,7 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi
|
||||
protected FollowsCurrentThreadAction actionFollowsCurrentThread;
|
||||
protected MultiStateDockingAction<AutoReadMemorySpec> actionAutoReadMemory;
|
||||
protected DockingAction actionExportView;
|
||||
protected DockingAction actionOpenProgram;
|
||||
|
||||
protected final DebuggerGoToDialog goToDialog;
|
||||
|
||||
@ -585,6 +589,15 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi
|
||||
}
|
||||
}
|
||||
|
||||
@AutoServiceConsumed
|
||||
private void setConsoleService(DebuggerConsoleService consoleService) {
|
||||
if (consoleService != null) {
|
||||
if (actionOpenProgram != null) {
|
||||
consoleService.addResolutionAction(actionOpenProgram);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void markTrackedStaticLocation(ProgramLocation location) {
|
||||
Swing.runIfSwingOrRunLater(() -> {
|
||||
if (location == null) {
|
||||
@ -606,6 +619,17 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi
|
||||
});
|
||||
}
|
||||
|
||||
public void programOpened(Program program) {
|
||||
if (!isMainListing()) {
|
||||
return;
|
||||
}
|
||||
DomainFile df = program.getDomainFile();
|
||||
DebuggerOpenProgramActionContext ctx = new DebuggerOpenProgramActionContext(df);
|
||||
if (consoleService != null) {
|
||||
consoleService.removeFromLog(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
public void programClosed(Program program) {
|
||||
if (program == markedProgram) {
|
||||
removeOldStaticTrackingMarker();
|
||||
@ -783,6 +807,11 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi
|
||||
.onAction(this::activatedExportView)
|
||||
.buildAndInstallLocal(this);
|
||||
|
||||
actionOpenProgram = OpenProgramAction.builder(plugin)
|
||||
.withContext(DebuggerOpenProgramActionContext.class)
|
||||
.onAction(this::activatedOpenProgram)
|
||||
.build();
|
||||
|
||||
contextChanged();
|
||||
}
|
||||
|
||||
@ -812,6 +841,11 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi
|
||||
tool.showDialog(dialog);
|
||||
}
|
||||
|
||||
private void activatedOpenProgram(DebuggerOpenProgramActionContext context) {
|
||||
programManager.openProgram(context.getDomainFile(), DomainFile.DEFAULT_VERSION,
|
||||
ProgramManager.OPEN_CURRENT);
|
||||
}
|
||||
|
||||
protected void activatedLocationTracking(ActionContext ctx) {
|
||||
doTrackSpec();
|
||||
}
|
||||
@ -934,7 +968,7 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi
|
||||
}
|
||||
|
||||
protected void doSyncToStatic(ProgramLocation location) {
|
||||
if (syncToStaticListing && location != null) {
|
||||
if (isSyncToStaticListing() && location != null) {
|
||||
ProgramLocation staticLoc = mappingService.getStaticLocationFromDynamic(location);
|
||||
if (staticLoc != null) {
|
||||
Swing.runIfSwingOrRunLater(() -> plugin.fireStaticLocationEvent(staticLoc));
|
||||
@ -942,8 +976,58 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi
|
||||
}
|
||||
}
|
||||
|
||||
protected void doTryOpenProgram(DomainFile df, int version, int state) {
|
||||
DebuggerOpenProgramActionContext ctx = new DebuggerOpenProgramActionContext(df);
|
||||
if (consoleService != null && consoleService.logContains(ctx)) {
|
||||
return;
|
||||
}
|
||||
if (df.canRecover()) {
|
||||
if (consoleService != null) {
|
||||
consoleService.log(DebuggerResources.ICON_MODULES, "<html>Program <b>" +
|
||||
HTMLUtilities.escapeHTML(df.getPathname()) +
|
||||
"</b> has recovery data. It must be opened manually.</html>", ctx);
|
||||
}
|
||||
return;
|
||||
}
|
||||
new TaskLauncher(new Task("Open " + df, true, false, false) {
|
||||
@Override
|
||||
public void run(TaskMonitor monitor) throws CancelledException {
|
||||
Program program = null;
|
||||
try {
|
||||
program = (Program) df.getDomainObject(this, false, false, monitor);
|
||||
programManager.openProgram(program, state);
|
||||
}
|
||||
catch (VersionException e) {
|
||||
if (consoleService != null) {
|
||||
consoleService.log(DebuggerResources.ICON_MODULES, "<html>Program <b>" +
|
||||
HTMLUtilities.escapeHTML(df.getPathname()) +
|
||||
"</b> was created with a different version of Ghidra." +
|
||||
" It must be opened manually.</html>", ctx);
|
||||
}
|
||||
return;
|
||||
}
|
||||
catch (Exception e) {
|
||||
if (consoleService != null) {
|
||||
consoleService.log(DebuggerResources.ICON_LOG_ERROR, "<html>Program <b>" +
|
||||
HTMLUtilities.escapeHTML(df.getPathname()) +
|
||||
"</b> could not be opened: " + e + ". Try opening it manually.</html>",
|
||||
ctx);
|
||||
}
|
||||
return;
|
||||
}
|
||||
finally {
|
||||
if (program != null) {
|
||||
program.release(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, tool.getToolFrame());
|
||||
}
|
||||
|
||||
protected void doCheckCurrentModuleMissing() {
|
||||
if (importerService == null || consoleService == null) {
|
||||
// Is there any reason to try to open the module if we're not syncing listings?
|
||||
// I don't think so.
|
||||
if (!isSyncToStaticListing()) {
|
||||
return;
|
||||
}
|
||||
Trace trace = current.getTrace();
|
||||
@ -967,9 +1051,7 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi
|
||||
DomainFile df = ProgramURLUtils.getFileForHackedUpGhidraURL(tool.getProject(),
|
||||
mapping.getStaticProgramURL());
|
||||
if (df != null) {
|
||||
// We're almost certainly preparing to goTo, so make it current
|
||||
programManager.openProgram(df, DomainFile.DEFAULT_VERSION,
|
||||
ProgramManager.OPEN_CURRENT);
|
||||
doTryOpenProgram(df, DomainFile.DEFAULT_VERSION, ProgramManager.OPEN_CURRENT);
|
||||
}
|
||||
}
|
||||
|
||||
@ -995,14 +1077,19 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi
|
||||
if (programManager != null && !toOpen.isEmpty()) {
|
||||
for (DomainFile df : toOpen) {
|
||||
// Do not presume a goTo is about to happen. There are no mappings, yet.
|
||||
programManager.openProgram(df, DomainFile.DEFAULT_VERSION,
|
||||
doTryOpenProgram(df, DomainFile.DEFAULT_VERSION,
|
||||
ProgramManager.OPEN_VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
if (importerService == null || consoleService == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (TraceModule mod : missing) {
|
||||
consoleService.log(DebuggerResources.ICON_LOG_ERROR,
|
||||
"<html>The module <b><tt>" + HTMLUtilities.escapeHTML(mod.getName()) +
|
||||
"</tt></b> was not found in the project",
|
||||
"</tt></b> was not found in the project</html>",
|
||||
new DebuggerMissingModuleActionContext(mod));
|
||||
}
|
||||
/**
|
||||
@ -1144,6 +1231,11 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
removeOldListeners();
|
||||
if (consoleService != null) {
|
||||
if (actionOpenProgram != null) {
|
||||
consoleService.removeResolutionAction(actionOpenProgram);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,55 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.plugin.core.debug.gui.listing;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import docking.ActionContext;
|
||||
import ghidra.framework.model.DomainFile;
|
||||
|
||||
public class DebuggerOpenProgramActionContext extends ActionContext {
|
||||
private final DomainFile df;
|
||||
private final int hashCode;
|
||||
|
||||
public DebuggerOpenProgramActionContext(DomainFile df) {
|
||||
this.df = df;
|
||||
this.hashCode = Objects.hash(getClass(), df);
|
||||
}
|
||||
|
||||
public DomainFile getDomainFile() {
|
||||
return df;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof DebuggerOpenProgramActionContext)) {
|
||||
return false;
|
||||
}
|
||||
DebuggerOpenProgramActionContext that = (DebuggerOpenProgramActionContext) obj;
|
||||
if (!this.df.equals(that.df)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -867,12 +867,12 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
|
||||
Msg.error(this, "Import service is not present");
|
||||
}
|
||||
importModuleFromFileSystem(context.getModule());
|
||||
consoleService.remove(context); // TODO: Should remove when mapping is created
|
||||
consoleService.removeFromLog(context); // TODO: Should remove when mapping is created
|
||||
}
|
||||
|
||||
private void activatedMapMissingModule(DebuggerMissingModuleActionContext context) {
|
||||
mapModuleTo(context.getModule());
|
||||
consoleService.remove(context); // TODO: Should remove when mapping is created
|
||||
consoleService.removeFromLog(context); // TODO: Should remove when mapping is created
|
||||
}
|
||||
|
||||
private void toggledFilter(ActionContext ignored) {
|
||||
|
@ -51,7 +51,15 @@ public interface DebuggerConsoleService extends DebuggerConsoleLogger {
|
||||
*
|
||||
* @param context the context of the entry to remove
|
||||
*/
|
||||
void remove(ActionContext context);
|
||||
void removeFromLog(ActionContext context);
|
||||
|
||||
/**
|
||||
* Check if the console contains an actionable message for the given context
|
||||
*
|
||||
* @param context the context to check for
|
||||
* @return true if present, false if absent
|
||||
*/
|
||||
boolean logContains(ActionContext context);
|
||||
|
||||
/**
|
||||
* Add an action which might be applied to an actionable log message
|
||||
|
@ -19,6 +19,7 @@ import static ghidra.lifecycle.Unfinished.TODO;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
@ -37,10 +38,13 @@ import ghidra.app.plugin.core.debug.gui.DebuggerResources;
|
||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractFollowsCurrentThreadAction;
|
||||
import ghidra.app.plugin.core.debug.gui.action.*;
|
||||
import ghidra.app.plugin.core.debug.gui.console.DebuggerConsolePlugin;
|
||||
import ghidra.app.plugin.core.debug.gui.console.DebuggerConsoleProvider.BoundAction;
|
||||
import ghidra.app.plugin.core.debug.gui.console.DebuggerConsoleProvider.LogRow;
|
||||
import ghidra.app.plugin.core.debug.gui.modules.DebuggerMissingModuleActionContext;
|
||||
import ghidra.app.services.*;
|
||||
import ghidra.app.util.viewer.listingpanel.ListingPanel;
|
||||
import ghidra.async.SwingExecutorService;
|
||||
import ghidra.framework.model.*;
|
||||
import ghidra.plugin.importer.ImporterPlugin;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.Register;
|
||||
@ -57,6 +61,9 @@ import ghidra.trace.model.modules.TraceModule;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.model.time.TraceSnapshot;
|
||||
import ghidra.util.database.UndoableTransaction;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.exception.VersionException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUITest {
|
||||
static LocationTrackingSpec getLocationTrackingSpec(String name) {
|
||||
@ -1351,4 +1358,127 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
||||
|
||||
assertEquals(tb.addr(0x00404321), listingProvider.getLocation().getAddress());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyncToStaticListingOpensModule() throws Exception {
|
||||
DebuggerConsolePlugin consolePlugin = addPlugin(tool, DebuggerConsolePlugin.class);
|
||||
|
||||
createAndOpenTrace();
|
||||
createAndOpenProgramFromTrace();
|
||||
intoProject(tb.trace);
|
||||
intoProject(program);
|
||||
|
||||
AddressSpace ss = program.getAddressFactory().getDefaultAddressSpace();
|
||||
try (UndoableTransaction tid = UndoableTransaction.start(program, "Add block", true)) {
|
||||
program.getMemory()
|
||||
.createInitializedBlock(".text", ss.getAddress(0x00600000), 0x10000, (byte) 0,
|
||||
monitor, false);
|
||||
}
|
||||
try (UndoableTransaction tid = tb.startTransaction()) {
|
||||
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
||||
memory.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff),
|
||||
TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE);
|
||||
TraceLocation from =
|
||||
new DefaultTraceLocation(tb.trace, null, Range.atLeast(0L), tb.addr(0x00400000));
|
||||
ProgramLocation to = new ProgramLocation(program, ss.getAddress(0x00600000));
|
||||
mappingService.addMapping(from, to, 0x8000, false);
|
||||
}
|
||||
waitForProgram(program);
|
||||
waitForDomainObject(tb.trace);
|
||||
|
||||
programManager.closeAllPrograms(true);
|
||||
waitForPass(() -> assertEquals(0, programManager.getAllOpenPrograms().length));
|
||||
|
||||
traceManager.activateTrace(tb.trace);
|
||||
waitForSwing();
|
||||
|
||||
listingProvider.getListingPanel()
|
||||
.setCursorPosition(
|
||||
new ProgramLocation(tb.trace.getProgramView(), tb.addr(0x00401234)),
|
||||
EventTrigger.GUI_ACTION);
|
||||
waitForSwing();
|
||||
|
||||
waitForPass(() -> assertEquals(1, programManager.getAllOpenPrograms().length));
|
||||
assertTrue(java.util.List.of(programManager.getAllOpenPrograms()).contains(program));
|
||||
|
||||
assertFalse(consolePlugin
|
||||
.logContains(new DebuggerOpenProgramActionContext(program.getDomainFile())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyncToStaticLogsRecoverableProgram() throws Exception {
|
||||
DebuggerConsolePlugin consolePlugin = addPlugin(tool, DebuggerConsolePlugin.class);
|
||||
|
||||
TestDummyDomainFolder root = new TestDummyDomainFolder(null, "root");
|
||||
DomainFile df = new TestDummyDomainFile(root, "dummyFile") {
|
||||
@Override
|
||||
public boolean canRecover() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
listingProvider.doTryOpenProgram(df, DomainFile.DEFAULT_VERSION,
|
||||
ProgramManager.OPEN_CURRENT);
|
||||
waitForSwing();
|
||||
|
||||
DebuggerOpenProgramActionContext ctx = new DebuggerOpenProgramActionContext(df);
|
||||
waitForPass(() -> assertTrue(consolePlugin.logContains(ctx)));
|
||||
assertTrue(consolePlugin.getLogRow(ctx).getMessage().contains("recovery"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyncToStaticLogsUpgradeableProgram() throws Exception {
|
||||
DebuggerConsolePlugin consolePlugin = addPlugin(tool, DebuggerConsolePlugin.class);
|
||||
|
||||
TestDummyDomainFolder root = new TestDummyDomainFolder(null, "root");
|
||||
DomainFile df = new TestDummyDomainFile(root, "dummyFile") {
|
||||
@Override
|
||||
public boolean canRecover() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainObject getDomainObject(Object consumer, boolean okToUpgrade,
|
||||
boolean okToRecover, TaskMonitor monitor)
|
||||
throws VersionException, IOException, CancelledException {
|
||||
throw new VersionException();
|
||||
}
|
||||
};
|
||||
|
||||
listingProvider.doTryOpenProgram(df, DomainFile.DEFAULT_VERSION,
|
||||
ProgramManager.OPEN_CURRENT);
|
||||
waitForSwing();
|
||||
|
||||
DebuggerOpenProgramActionContext ctx = new DebuggerOpenProgramActionContext(df);
|
||||
waitForPass(() -> assertTrue(consolePlugin.logContains(ctx)));
|
||||
assertTrue(consolePlugin.getLogRow(ctx).getMessage().contains("version"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testActionOpenProgram() throws Exception {
|
||||
DebuggerConsolePlugin consolePlugin = addPlugin(tool, DebuggerConsolePlugin.class);
|
||||
|
||||
createProgram();
|
||||
intoProject(program);
|
||||
|
||||
assertEquals(0, programManager.getAllOpenPrograms().length);
|
||||
|
||||
DebuggerOpenProgramActionContext ctx =
|
||||
new DebuggerOpenProgramActionContext(program.getDomainFile());
|
||||
consolePlugin.log(DebuggerResources.ICON_MODULES, "Test resolution", ctx);
|
||||
waitForSwing();
|
||||
|
||||
LogRow row = consolePlugin.getLogRow(ctx);
|
||||
assertEquals(1, row.getActions().size());
|
||||
BoundAction boundAction = row.getActions().get(0);
|
||||
assertEquals(listingProvider.actionOpenProgram, boundAction.action);
|
||||
|
||||
boundAction.perform();
|
||||
waitForSwing();
|
||||
|
||||
waitForPass(() -> assertEquals(1, programManager.getAllOpenPrograms().length));
|
||||
assertTrue(java.util.List.of(programManager.getAllOpenPrograms()).contains(program));
|
||||
// TODO: Test this independent of this particular action?
|
||||
assertNull(consolePlugin.getLogRow(ctx));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user