mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
GP-2623: Improve connect dialog and factory descriptions
This commit is contained in:
parent
5195aaebc1
commit
8dbf2341b2
30 changed files with 565 additions and 333 deletions
|
@ -34,10 +34,12 @@ import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
|
|||
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
|
||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources.*;
|
||||
import ghidra.app.services.DebuggerModelService;
|
||||
import ghidra.app.services.ProgramManager;
|
||||
import ghidra.dbg.DebuggerObjectModel;
|
||||
import ghidra.framework.plugintool.AutoService;
|
||||
import ghidra.framework.plugintool.ComponentProviderAdapter;
|
||||
import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
|
||||
import ghidra.program.model.listing.Program;
|
||||
|
||||
public class DebuggerTargetsProvider extends ComponentProviderAdapter {
|
||||
|
||||
|
@ -107,7 +109,9 @@ public class DebuggerTargetsProvider extends ComponentProviderAdapter {
|
|||
public void actionPerformed(ActionContext context) {
|
||||
// NB. Drop the future on the floor, because the UI will report issues.
|
||||
// Cancellation should be ignored.
|
||||
modelService.showConnectDialog();
|
||||
ProgramManager programManager = tool.getService(ProgramManager.class);
|
||||
Program program = programManager == null ? null : programManager.getCurrentProgram();
|
||||
modelService.showConnectDialog(program);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -37,7 +37,6 @@ public class DbgDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOpi
|
|||
protected List<String> getLauncherPath() {
|
||||
return PathUtils.parse("");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected class InVmDbgengDebuggerProgramLaunchOffer
|
||||
|
@ -133,7 +132,7 @@ public class DbgDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOpi
|
|||
}
|
||||
List<DebuggerProgramLaunchOffer> offers = new ArrayList<>();
|
||||
for (DebuggerModelFactory factory : service.getModelFactories()) {
|
||||
if (!factory.isCompatible()) {
|
||||
if (!factory.isCompatible(program)) {
|
||||
continue;
|
||||
}
|
||||
String clsName = factory.getClass().getName();
|
||||
|
|
|
@ -95,7 +95,7 @@ public class FridaDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchO
|
|||
}
|
||||
List<DebuggerProgramLaunchOffer> offers = new ArrayList<>();
|
||||
for (DebuggerModelFactory factory : service.getModelFactories()) {
|
||||
if (!factory.isCompatible()) {
|
||||
if (!factory.isCompatible(program)) {
|
||||
continue;
|
||||
}
|
||||
String clsName = factory.getClass().getName();
|
||||
|
|
|
@ -139,7 +139,7 @@ public class GdbDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOpi
|
|||
}
|
||||
List<DebuggerProgramLaunchOffer> offers = new ArrayList<>();
|
||||
for (DebuggerModelFactory factory : service.getModelFactories()) {
|
||||
if (!factory.isCompatible()) {
|
||||
if (!factory.isCompatible(program)) {
|
||||
continue;
|
||||
}
|
||||
String clsName = factory.getClass().getName();
|
||||
|
|
|
@ -90,7 +90,7 @@ public class LldbDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOp
|
|||
}
|
||||
List<DebuggerProgramLaunchOffer> offers = new ArrayList<>();
|
||||
for (DebuggerModelFactory factory : service.getModelFactories()) {
|
||||
if (!factory.isCompatible()) {
|
||||
if (!factory.isCompatible(program)) {
|
||||
continue;
|
||||
}
|
||||
String clsName = factory.getClass().getName();
|
||||
|
|
|
@ -26,6 +26,7 @@ import java.util.concurrent.CompletableFuture;
|
|||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.text.View;
|
||||
|
||||
import org.apache.commons.collections4.BidiMap;
|
||||
import org.apache.commons.collections4.bidimap.DualLinkedHashBidiMap;
|
||||
|
@ -40,13 +41,14 @@ import ghidra.dbg.DebuggerModelFactory;
|
|||
import ghidra.dbg.DebuggerObjectModel;
|
||||
import ghidra.dbg.util.ConfigurableFactory.Property;
|
||||
import ghidra.framework.options.SaveState;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.datastruct.CollectionChangeListener;
|
||||
import ghidra.util.layout.PairLayout;
|
||||
|
||||
public class DebuggerConnectDialog extends DialogComponentProvider
|
||||
implements PropertyChangeListener {
|
||||
private static final String KEY_FACTORY_CLASSNAME = "factoryClassname";
|
||||
private static final String KEY_CURRENT_FACTORY_CLASSNAME = "currentFactoryCls";
|
||||
private static final String KEY_SUCCESS_FACTORY_CLASSNAME = "successFactoryCls";
|
||||
private static final String HTML_BOLD_DESCRIPTION = "<html><b>Description:</b> ";
|
||||
|
||||
protected class FactoriesChangedListener
|
||||
|
@ -67,9 +69,40 @@ public class DebuggerConnectDialog extends DialogComponentProvider
|
|||
}
|
||||
}
|
||||
|
||||
protected record FactoryEntry(DebuggerModelFactory factory) {
|
||||
@Override
|
||||
public String toString() {
|
||||
return factory.getBrief();
|
||||
}
|
||||
}
|
||||
|
||||
protected record PrioritizedFactory(FactoryEntry entry, int priority) {
|
||||
public PrioritizedFactory(FactoryEntry ent, Program program) {
|
||||
this(ent, ent.factory.getPriority(program));
|
||||
}
|
||||
}
|
||||
|
||||
protected enum NameComparator implements Comparator<String> {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public int compare(String o1, String o2) {
|
||||
boolean p1 = o1.startsWith("PROTOTYPE:");
|
||||
boolean p2 = o2.startsWith("PROTOTYPE:");
|
||||
if (p1 && !p2) {
|
||||
return 1;
|
||||
}
|
||||
if (!p1 && p2) {
|
||||
return -1;
|
||||
}
|
||||
return o1.toLowerCase().compareTo(o2.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
private DebuggerModelService modelService;
|
||||
|
||||
private DebuggerModelFactory factory;
|
||||
private DebuggerModelFactory currentFactory;
|
||||
private DebuggerModelFactory successFactory;
|
||||
private final Map<DebuggerModelFactory, FactoryEntry> factories = new HashMap<>();
|
||||
private FactoriesChangedListener listener = new FactoriesChangedListener();
|
||||
|
||||
|
@ -81,26 +114,12 @@ public class DebuggerConnectDialog extends DialogComponentProvider
|
|||
private final Map<Property<?>, Component> components = new LinkedHashMap<>();
|
||||
|
||||
protected JLabel description;
|
||||
protected JPanel pairPanel;
|
||||
private PairLayout layout;
|
||||
protected JPanel gridPanel;
|
||||
|
||||
protected JButton connectButton;
|
||||
protected CompletableFuture<? extends DebuggerObjectModel> futureConnect;
|
||||
protected CompletableFuture<DebuggerObjectModel> result;
|
||||
|
||||
protected static class FactoryEntry {
|
||||
DebuggerModelFactory factory;
|
||||
|
||||
public FactoryEntry(DebuggerModelFactory factory) {
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return factory.getBrief();
|
||||
}
|
||||
}
|
||||
|
||||
public DebuggerConnectDialog() {
|
||||
super(AbstractConnectAction.NAME, true, true, true, false);
|
||||
|
||||
|
@ -126,7 +145,7 @@ public class DebuggerConnectDialog extends DialogComponentProvider
|
|||
toAdd.add(entry);
|
||||
}
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
toAdd.sort(Comparator.comparing(FactoryEntry::toString));
|
||||
toAdd.sort(Comparator.comparing(FactoryEntry::toString, NameComparator.INSTANCE));
|
||||
for (FactoryEntry entry : toAdd) {
|
||||
dropdownModel.addElement(entry);
|
||||
}
|
||||
|
@ -190,20 +209,20 @@ public class DebuggerConnectDialog extends DialogComponentProvider
|
|||
JPanel inner = new JPanel(new BorderLayout());
|
||||
description = new JLabel(HTML_BOLD_DESCRIPTION + "</html>");
|
||||
description.setBorder(new EmptyBorder(10, 0, 10, 0));
|
||||
description.setPreferredSize(new Dimension(400, 150));
|
||||
inner.add(description);
|
||||
topBox.add(inner);
|
||||
|
||||
panel.add(topBox, BorderLayout.NORTH);
|
||||
|
||||
layout = new PairLayout(5, 5);
|
||||
pairPanel = new JPanel(layout);
|
||||
gridPanel = new JPanel(new GridBagLayout());
|
||||
|
||||
JPanel centering = new JPanel(new FlowLayout(FlowLayout.CENTER));
|
||||
JScrollPane scrolling = new JScrollPane(centering, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
|
||||
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
scrolling.setPreferredSize(new Dimension(100, 130));
|
||||
scrolling.setPreferredSize(new Dimension(100, 200));
|
||||
panel.add(scrolling, BorderLayout.CENTER);
|
||||
centering.add(pairPanel);
|
||||
centering.add(gridPanel);
|
||||
|
||||
addWorkPanel(panel);
|
||||
|
||||
|
@ -219,13 +238,15 @@ public class DebuggerConnectDialog extends DialogComponentProvider
|
|||
|
||||
private void itemSelected(ItemEvent evt) {
|
||||
if (evt.getStateChange() == ItemEvent.DESELECTED) {
|
||||
pairPanel.removeAll();
|
||||
gridPanel.removeAll();
|
||||
}
|
||||
else if (evt.getStateChange() == ItemEvent.SELECTED) {
|
||||
FactoryEntry ent = (FactoryEntry) evt.getItem();
|
||||
factory = ent.factory;
|
||||
currentFactory = ent.factory;
|
||||
populateOptions();
|
||||
//repack();
|
||||
/**
|
||||
* Don't repack here. It can shrink the dialog, which may not be what the user wants.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,7 +260,7 @@ public class DebuggerConnectDialog extends DialogComponentProvider
|
|||
}
|
||||
setStatusText("Connecting...");
|
||||
synchronized (this) {
|
||||
futureConnect = factory.build();
|
||||
futureConnect = currentFactory.build();
|
||||
}
|
||||
futureConnect.thenCompose(m -> m.fetchModelRoot()).thenAcceptAsync(r -> {
|
||||
DebuggerObjectModel m = r.getModel();
|
||||
|
@ -268,6 +289,7 @@ public class DebuggerConnectDialog extends DialogComponentProvider
|
|||
synchronized (this) {
|
||||
futureConnect = null;
|
||||
}
|
||||
successFactory = currentFactory;
|
||||
connectButton.setEnabled(true);
|
||||
});
|
||||
}
|
||||
|
@ -284,7 +306,7 @@ public class DebuggerConnectDialog extends DialogComponentProvider
|
|||
}
|
||||
|
||||
protected synchronized CompletableFuture<DebuggerObjectModel> reset(
|
||||
DebuggerModelFactory factory) {
|
||||
DebuggerModelFactory factory, Program program) {
|
||||
if (factory != null) {
|
||||
synchronized (factories) {
|
||||
dropdownModel.setSelectedItem(factories.get(factory));
|
||||
|
@ -292,6 +314,7 @@ public class DebuggerConnectDialog extends DialogComponentProvider
|
|||
dropdown.setEnabled(false);
|
||||
}
|
||||
else {
|
||||
selectCompatibleFactory(program);
|
||||
dropdown.setEnabled(true);
|
||||
}
|
||||
|
||||
|
@ -311,18 +334,42 @@ public class DebuggerConnectDialog extends DialogComponentProvider
|
|||
}
|
||||
|
||||
protected void populateOptions() {
|
||||
description.setText(
|
||||
HTML_BOLD_DESCRIPTION + HTMLUtilities.friendlyEncodeHTML(factory.getHtmlDetails()));
|
||||
description.setText(HTML_BOLD_DESCRIPTION + currentFactory.getHtmlDetails());
|
||||
|
||||
propertyEditors.clear();
|
||||
components.clear();
|
||||
Map<String, Property<?>> optsMap = factory.getOptions();
|
||||
//layout.setRows(Math.max(1, optsMap.size()));
|
||||
pairPanel.removeAll();
|
||||
Map<String, Property<?>> optsMap = currentFactory.getOptions();
|
||||
gridPanel.removeAll();
|
||||
GridBagConstraints constraints;
|
||||
|
||||
if (optsMap.isEmpty()) {
|
||||
JLabel label =
|
||||
new JLabel("<html>There are no configuration options for this connector.");
|
||||
constraints = new GridBagConstraints();
|
||||
gridPanel.add(label, constraints);
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for (Map.Entry<String, Property<?>> opt : optsMap.entrySet()) {
|
||||
Property<?> property = opt.getValue();
|
||||
JLabel label = new JLabel(opt.getKey());
|
||||
pairPanel.add(label);
|
||||
JLabel label = new JLabel("<html>" + HTMLUtilities.escapeHTML(opt.getKey())) {
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
View v = (View) getClientProperty("html");
|
||||
if (v == null) {
|
||||
return super.getPreferredSize();
|
||||
}
|
||||
v.setSize(200, 0);
|
||||
float height = v.getPreferredSpan(View.Y_AXIS);
|
||||
return new Dimension(200, (int) height);
|
||||
}
|
||||
};
|
||||
constraints = new GridBagConstraints();
|
||||
constraints.fill = GridBagConstraints.BOTH;
|
||||
constraints.gridx = 0;
|
||||
constraints.gridy = i;
|
||||
constraints.insets = new Insets(i == 0 ? 0 : 5, 0, 0, 5);
|
||||
gridPanel.add(label, constraints);
|
||||
|
||||
Class<?> type = property.getValueClass();
|
||||
PropertyEditor editor = PropertyEditorManager.findEditor(type);
|
||||
|
@ -331,11 +378,22 @@ public class DebuggerConnectDialog extends DialogComponentProvider
|
|||
}
|
||||
editor.setValue(property.getValue());
|
||||
editor.addPropertyChangeListener(this);
|
||||
Component comp = MiscellaneousUtils.getEditorComponent(editor);
|
||||
pairPanel.add(comp);
|
||||
Component editorComponent = MiscellaneousUtils.getEditorComponent(editor);
|
||||
if (editorComponent instanceof JTextField textField) {
|
||||
textField.setColumns(13);
|
||||
}
|
||||
constraints = new GridBagConstraints();
|
||||
constraints.fill = GridBagConstraints.HORIZONTAL;
|
||||
constraints.anchor = GridBagConstraints.WEST;
|
||||
constraints.gridx = 1;
|
||||
constraints.gridy = i;
|
||||
constraints.insets = new Insets(i == 0 ? 0 : 5, 0, 0, 0);
|
||||
gridPanel.add(editorComponent, constraints);
|
||||
|
||||
propertyEditors.put(property, editor);
|
||||
components.put(property, comp);
|
||||
components.put(property, editorComponent);
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -350,24 +408,75 @@ public class DebuggerConnectDialog extends DialogComponentProvider
|
|||
}
|
||||
|
||||
public void writeConfigState(SaveState saveState) {
|
||||
if (factory != null) {
|
||||
saveState.putString(KEY_FACTORY_CLASSNAME, factory.getClass().getName());
|
||||
if (currentFactory != null) {
|
||||
saveState.putString(KEY_CURRENT_FACTORY_CLASSNAME, currentFactory.getClass().getName());
|
||||
}
|
||||
if (successFactory != null) {
|
||||
saveState.putString(KEY_SUCCESS_FACTORY_CLASSNAME, successFactory.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
public void readConfigState(SaveState saveState) {
|
||||
String factoryName = saveState.getString(KEY_FACTORY_CLASSNAME, null);
|
||||
if (factoryName == null) {
|
||||
return;
|
||||
}
|
||||
protected FactoryEntry getByName(String className) {
|
||||
synchronized (factories) {
|
||||
for (Map.Entry<DebuggerModelFactory, FactoryEntry> ent : factories.entrySet()) {
|
||||
String name = ent.getKey().getClass().getName();
|
||||
if (factoryName.equals(name)) {
|
||||
factory = ent.getKey();
|
||||
dropdown.setSelectedItem(ent.getValue());
|
||||
for (FactoryEntry ent : factories.values()) {
|
||||
String name = ent.factory.getClass().getName();
|
||||
if (className.equals(name)) {
|
||||
return ent;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected Collection<PrioritizedFactory> getByPriority(Program program) {
|
||||
synchronized (factories) {
|
||||
return factories.values()
|
||||
.stream()
|
||||
.map(e -> new PrioritizedFactory(e, program))
|
||||
.sorted(Comparator.comparing(pf -> -pf.priority()))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
||||
protected PrioritizedFactory getFirstCompatibleByPriority(Program program) {
|
||||
for (PrioritizedFactory pf : getByPriority(program)) {
|
||||
if (pf.priority >= 0) {
|
||||
return pf;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void selectCompatibleFactory(Program program) {
|
||||
if (currentFactory != null && currentFactory.isCompatible(program)) {
|
||||
return;
|
||||
}
|
||||
if (successFactory != null && successFactory.isCompatible(program)) {
|
||||
currentFactory = successFactory;
|
||||
synchronized (factories) {
|
||||
dropdown.setSelectedItem(factories.get(successFactory));
|
||||
}
|
||||
return;
|
||||
}
|
||||
PrioritizedFactory compat = getFirstCompatibleByPriority(program);
|
||||
if (compat == null) {
|
||||
return;
|
||||
}
|
||||
currentFactory = compat.entry.factory;
|
||||
dropdown.setSelectedItem(compat.entry);
|
||||
}
|
||||
|
||||
public void readConfigState(SaveState saveState) {
|
||||
String currentFactoryName = saveState.getString(KEY_CURRENT_FACTORY_CLASSNAME, null);
|
||||
FactoryEntry restoreCurrent =
|
||||
currentFactoryName == null ? null : getByName(currentFactoryName);
|
||||
currentFactory = restoreCurrent == null ? null : restoreCurrent.factory;
|
||||
dropdown.setSelectedItem(restoreCurrent);
|
||||
|
||||
String successFactoryName = saveState.getString(KEY_SUCCESS_FACTORY_CLASSNAME, null);
|
||||
FactoryEntry restoreSuccess =
|
||||
successFactoryName == null ? null : getByName(successFactoryName);
|
||||
successFactory = restoreSuccess == null ? null : restoreSuccess.factory;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -641,14 +641,24 @@ public class DebuggerModelServicePlugin extends Plugin
|
|||
}
|
||||
|
||||
protected CompletableFuture<DebuggerObjectModel> doShowConnectDialog(PluginTool tool,
|
||||
DebuggerModelFactory factory) {
|
||||
CompletableFuture<DebuggerObjectModel> future = connectDialog.reset(factory);
|
||||
DebuggerModelFactory factory, Program program) {
|
||||
CompletableFuture<DebuggerObjectModel> future = connectDialog.reset(factory, program);
|
||||
tool.showDialog(connectDialog);
|
||||
return future;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<DebuggerObjectModel> showConnectDialog() {
|
||||
return doShowConnectDialog(tool, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<DebuggerObjectModel> showConnectDialog(Program program) {
|
||||
return doShowConnectDialog(tool, null, program);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<DebuggerObjectModel> showConnectDialog(DebuggerModelFactory factory) {
|
||||
return doShowConnectDialog(tool, factory);
|
||||
return doShowConnectDialog(tool, factory, null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -269,9 +269,19 @@ public class DebuggerModelServiceProxyPlugin extends Plugin
|
|||
closeAllModels();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<DebuggerObjectModel> showConnectDialog() {
|
||||
return delegate.doShowConnectDialog(tool, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<DebuggerObjectModel> showConnectDialog(Program program) {
|
||||
return delegate.doShowConnectDialog(tool, null, program);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<DebuggerObjectModel> showConnectDialog(DebuggerModelFactory factory) {
|
||||
return delegate.doShowConnectDialog(tool, factory);
|
||||
return delegate.doShowConnectDialog(tool, factory, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -353,14 +353,20 @@ public interface DebuggerModelService {
|
|||
*
|
||||
* @return a future which completes with the new connection, possibly cancelled
|
||||
*/
|
||||
default CompletableFuture<DebuggerObjectModel> showConnectDialog() {
|
||||
return showConnectDialog(null);
|
||||
}
|
||||
CompletableFuture<DebuggerObjectModel> showConnectDialog();
|
||||
|
||||
/**
|
||||
* Prompt the user to create a new connection, hinting at the program to launch
|
||||
*
|
||||
* @param program the current program used to help select a default
|
||||
* @return a future which completes with the new connection, possibly cancelled
|
||||
*/
|
||||
CompletableFuture<DebuggerObjectModel> showConnectDialog(Program program);
|
||||
|
||||
/**
|
||||
* Prompt the user to create a new connection, optionally fixing the factory
|
||||
*
|
||||
* @param factory the required factory, or null for user selection
|
||||
* @param factory the required factory
|
||||
* @return a future which completes with the new connection, possible cancelled
|
||||
*/
|
||||
CompletableFuture<DebuggerObjectModel> showConnectDialog(DebuggerModelFactory factory);
|
||||
|
|
|
@ -473,15 +473,15 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
|||
DebuggerConnectDialog dialog = waitForDialogComponent(DebuggerConnectDialog.class);
|
||||
|
||||
FactoryEntry fe = (FactoryEntry) dialog.dropdownModel.getSelectedItem();
|
||||
assertEquals(mb.testFactory, fe.factory);
|
||||
assertEquals(mb.testFactory, fe.factory());
|
||||
|
||||
assertEquals(TestDebuggerModelFactory.FAKE_DETAILS_HTML, dialog.description.getText());
|
||||
|
||||
Component[] components = dialog.pairPanel.getComponents();
|
||||
Component[] components = dialog.gridPanel.getComponents();
|
||||
|
||||
assertTrue(components[0] instanceof JLabel);
|
||||
JLabel label = (JLabel) components[0];
|
||||
assertEquals(TestDebuggerModelFactory.FAKE_OPTION_NAME, label.getText());
|
||||
assertEquals("<html>" + TestDebuggerModelFactory.FAKE_OPTION_NAME, label.getText());
|
||||
|
||||
assertTrue(components[1] instanceof JTextField);
|
||||
JTextField field = (JTextField) components[1];
|
||||
|
@ -518,7 +518,7 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
|||
DebuggerConnectDialog connectDialog = waitForDialogComponent(DebuggerConnectDialog.class);
|
||||
|
||||
FactoryEntry fe = (FactoryEntry) connectDialog.dropdownModel.getSelectedItem();
|
||||
assertEquals(mb.testFactory, fe.factory);
|
||||
assertEquals(mb.testFactory, fe.factory());
|
||||
|
||||
pressButtonByText(connectDialog, AbstractConnectAction.NAME, true);
|
||||
// NOTE: testModel is null. Don't use #createTestModel(), which adds to service
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue