mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
932 lines
31 KiB
Java
932 lines
31 KiB
Java
/* ###
|
|
* 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 help.screenshot;
|
|
|
|
import static org.junit.Assert.*;
|
|
|
|
import java.awt.*;
|
|
import java.io.FileNotFoundException;
|
|
import java.util.ArrayList;
|
|
import java.util.Collection;
|
|
import java.util.List;
|
|
|
|
import javax.swing.*;
|
|
import javax.swing.table.TableModel;
|
|
|
|
import org.junit.*;
|
|
|
|
import docking.*;
|
|
import docking.action.DockingActionIf;
|
|
import docking.action.ToggleDockingAction;
|
|
import docking.options.editor.OptionsDialog;
|
|
import docking.options.editor.OptionsPanel;
|
|
import docking.widgets.tree.GTree;
|
|
import ghidra.app.util.viewer.listingpanel.ListingCodeComparisonPanel;
|
|
import ghidra.feature.vt.api.correlator.program.ExactMatchInstructionsProgramCorrelatorFactory;
|
|
import ghidra.feature.vt.api.correlator.program.SymbolNameProgramCorrelatorFactory;
|
|
import ghidra.feature.vt.api.main.*;
|
|
import ghidra.feature.vt.api.markupitem.AbstractFunctionSignatureMarkupTest;
|
|
import ghidra.feature.vt.api.markuptype.VTMarkupType;
|
|
import ghidra.feature.vt.gui.VTTestEnv;
|
|
import ghidra.feature.vt.gui.filters.AncillaryFilterDialogComponentProvider;
|
|
import ghidra.feature.vt.gui.plugin.*;
|
|
import ghidra.feature.vt.gui.provider.functionassociation.VTFunctionAssociationProvider;
|
|
import ghidra.feature.vt.gui.provider.impliedmatches.VTImpliedMatchesTableProvider;
|
|
import ghidra.feature.vt.gui.provider.markuptable.*;
|
|
import ghidra.feature.vt.gui.provider.matchtable.DisplayableLabel;
|
|
import ghidra.feature.vt.gui.provider.matchtable.VTMatchTableProvider;
|
|
import ghidra.feature.vt.gui.provider.onetomany.VTMatchDestinationTableProvider;
|
|
import ghidra.feature.vt.gui.provider.onetomany.VTMatchSourceTableProvider;
|
|
import ghidra.feature.vt.gui.task.*;
|
|
import ghidra.feature.vt.gui.util.MatchInfo;
|
|
import ghidra.feature.vt.gui.wizard.*;
|
|
import ghidra.framework.main.DataTreeDialog;
|
|
import ghidra.framework.main.datatree.DataTree;
|
|
import ghidra.framework.main.datatree.ProjectDataTreePanel;
|
|
import ghidra.framework.options.ToolOptions;
|
|
import ghidra.framework.plugintool.PluginTool;
|
|
import ghidra.program.model.address.Address;
|
|
import ghidra.program.model.listing.Function;
|
|
import ghidra.program.model.listing.Program;
|
|
import ghidra.program.model.symbol.Symbol;
|
|
import ghidra.program.model.symbol.SymbolTable;
|
|
import ghidra.util.Msg;
|
|
import ghidra.util.exception.UsrException;
|
|
import ghidra.util.table.GhidraTable;
|
|
import ghidra.util.task.*;
|
|
|
|
public class VersionTrackingPluginScreenShots extends GhidraScreenShotGenerator {
|
|
|
|
protected static final String TEST_SOURCE_PROGRAM_NAME = "VersionTracking/WallaceSrc";
|
|
protected static final String TEST_DESTINATION_PROGRAM_NAME = "VersionTracking/WallaceVersion2";
|
|
|
|
protected VTTestEnv vtTestEnv;
|
|
protected VTProgramCorrelator correlator;
|
|
protected Program sourceProgram;
|
|
protected Program destinationProgram;
|
|
protected VTController controller;
|
|
protected VTSession session;
|
|
protected Address sourceAddress;
|
|
protected Address destinationAddress;
|
|
protected VTMatch testMatch;
|
|
protected Function sourceFunction;
|
|
protected Function destinationFunction;
|
|
|
|
protected PluginTool vtTool;
|
|
protected VTPlugin vtPlugin;
|
|
|
|
@Before
|
|
@Override
|
|
public void setUp() throws Exception {
|
|
vtTestEnv = new VTTestEnv();
|
|
session = vtTestEnv.createSession(TEST_SOURCE_PROGRAM_NAME, TEST_DESTINATION_PROGRAM_NAME);
|
|
correlator = vtTestEnv.correlate(new ExactMatchInstructionsProgramCorrelatorFactory(),
|
|
null, TaskMonitor.DUMMY);
|
|
sourceProgram = vtTestEnv.getSourceProgram();
|
|
destinationProgram = vtTestEnv.getDestinationProgram();
|
|
controller = vtTestEnv.getVTController();
|
|
vtTool = vtTestEnv.showTool();
|
|
vtPlugin = vtTestEnv.getPlugin(VTPlugin.class);
|
|
tool = vtTool;
|
|
}
|
|
|
|
@After
|
|
@Override
|
|
public void tearDown() {
|
|
sourceProgram = null;
|
|
destinationProgram = null;
|
|
session = null;
|
|
controller = null;
|
|
correlator = null;
|
|
vtTestEnv.dispose();
|
|
saveOrDisplayImage();
|
|
}
|
|
|
|
@Test
|
|
public void testVTOptions_AcceptMatchDialog() throws Exception {
|
|
// invoke VTMatchApplySettingsAction and then change selection in tree.
|
|
DockingActionIf dockingAction = getAction(vtPlugin, "Version Tracking Options");
|
|
performAction(dockingAction, false);
|
|
|
|
OptionsDialog dialogProvider = waitForDialogComponent(OptionsDialog.class);
|
|
waitForSwing();
|
|
OptionsPanel optionsPanel = (OptionsPanel) getInstanceField("panel", dialogProvider);
|
|
final GTree gtree = (GTree) getInstanceField("gTree", optionsPanel);
|
|
runSwing(() -> gtree.setSelectedNodeByNamePath(
|
|
new String[] { "Options", "Version Tracking", "Accept Match Options" }));
|
|
waitForSwing();
|
|
|
|
captureDialog(900, 600);
|
|
pressButtonByText(getDialog(), "Cancel");
|
|
}
|
|
|
|
@Test
|
|
public void testVTOptions_ApplyMarkupDialog() throws Exception {
|
|
// invoke VTMatchApplySettingsAction
|
|
DockingActionIf dockingAction = getAction(vtPlugin, "Version Tracking Options");
|
|
performAction(dockingAction, false);
|
|
captureDialog(1250, 750);
|
|
pressButtonByText(getDialog(), "Cancel");
|
|
}
|
|
|
|
@Test
|
|
public void testFunctionsTable() throws Exception {
|
|
|
|
setToolSize(1200, 550);
|
|
|
|
showProvider(VTFunctionAssociationProvider.class);
|
|
hideDualListing(VTFunctionAssociationProvider.class);
|
|
captureIsolatedProvider(VTFunctionAssociationProvider.class, 1100, 350);
|
|
|
|
// Close the provider that was opened so tests that follow this one don't get messed up.
|
|
closeProvider(VTFunctionAssociationProvider.class);
|
|
}
|
|
|
|
@Test
|
|
public void testImpliedMatchesTable() throws Exception {
|
|
// We want the match table and implied match table in the tool.
|
|
// So close the markup items table provider.
|
|
closeProvider(VTMarkupItemsTableProvider.class);
|
|
|
|
setToolSize(1200, 550);
|
|
|
|
selectMatch("main");
|
|
|
|
captureToolWindow(1200, 550);
|
|
|
|
// Open the closed provider so that tests that follow this one don't get messed up.
|
|
showProvider(VTMarkupItemsTableProvider.class);
|
|
}
|
|
|
|
@Test
|
|
public void testVersionTrackingMarkupItems() throws Exception {
|
|
|
|
VTMatch match = getMatch("Call_strncpy_s", VTAssociationType.FUNCTION);
|
|
replaceMarkup(match, "00411ab0", "Function Signature");
|
|
addMarkup(match, "00411ad3", "EOL Comment");
|
|
tagMarkup(VTMarkupItemConsideredStatus.IGNORE_DONT_CARE, match, "00411ad7", "EOL Comment");
|
|
tagMarkup(VTMarkupItemConsideredStatus.REJECT, match, "00411ad8", "EOL Comment");
|
|
|
|
selectMatch("Call_strncpy_s");
|
|
|
|
setToolSize(1300, 750);
|
|
|
|
setMarkupTableDivider(40);
|
|
|
|
captureIsolatedProvider(VTMarkupItemsTableProvider.class, 1100, 700);
|
|
}
|
|
|
|
@Test
|
|
public void testMarkupItemsFilters() throws Exception {
|
|
Window window = waitForWindowByTitleContaining("Test Tool");
|
|
assertNotNull(window);
|
|
VTMarkupItemsTableProvider provider =
|
|
waitForComponentProvider(VTMarkupItemsTableProvider.class);
|
|
|
|
@SuppressWarnings("unchecked")
|
|
final AncillaryFilterDialogComponentProvider<VTMarkupItem> ancillaryFilterDialog =
|
|
(AncillaryFilterDialogComponentProvider<VTMarkupItem>) getInstanceField(
|
|
"ancillaryFilterDialog", provider);
|
|
|
|
runSwing(() -> tool.showDialog(ancillaryFilterDialog), false);
|
|
waitForSwing();
|
|
|
|
captureDialog(800, 250);
|
|
pressButtonByText(getDialog(), "OK");
|
|
}
|
|
|
|
@Test
|
|
public void testVersionTrackingMarkupItemsTableOnly() throws Exception {
|
|
|
|
VTMatch match = getMatch("Call_strncpy_s", VTAssociationType.FUNCTION);
|
|
replaceMarkup(match, "00411ab0", "Function Signature");
|
|
addMarkup(match, "00411ad3", "EOL Comment");
|
|
tagMarkup(VTMarkupItemConsideredStatus.IGNORE_DONT_CARE, match, "00411ad7", "EOL Comment");
|
|
tagMarkup(VTMarkupItemConsideredStatus.REJECT, match, "00411ad8", "EOL Comment");
|
|
|
|
selectMatch("Call_strncpy_s");
|
|
|
|
dualListingIsVisible(getProvider(VTMarkupItemsTableProvider.class));
|
|
|
|
hideDualListing(VTMarkupItemsTableProvider.class);
|
|
|
|
dualListingIsVisible(getProvider(VTMarkupItemsTableProvider.class));
|
|
|
|
setToolSize(1300, 750);
|
|
|
|
captureIsolatedProvider(VTMarkupItemsTableProvider.class, 1100, 280);
|
|
}
|
|
|
|
@Test
|
|
public void testVersionTrackingMarkupItemsHeader() throws Exception {
|
|
|
|
VTMatch match = getMatch("Call_strncpy_s", VTAssociationType.FUNCTION);
|
|
replaceMarkup(match, "00411ab0", "Function Signature");
|
|
addMarkup(match, "00411ad3", "EOL Comment");
|
|
tagMarkup(VTMarkupItemConsideredStatus.IGNORE_DONT_CARE, match, "00411ad7", "EOL Comment");
|
|
tagMarkup(VTMarkupItemConsideredStatus.REJECT, match, "00411ad8", "EOL Comment");
|
|
|
|
setToolSize(1300, 750);
|
|
|
|
selectMatch("Call_strncpy_s");
|
|
|
|
setDualListingHorizontal(VTMarkupItemsTableProvider.class);
|
|
toggleDualListingHeader(VTMarkupItemsTableProvider.class, true);
|
|
|
|
setMarkupTableDivider(10);
|
|
|
|
captureIsolatedProvider(VTMarkupItemsTableProvider.class, 1100, 1000);
|
|
|
|
toggleDualListingHeader(VTMarkupItemsTableProvider.class, false);// Switch header back so we don't mess up later tests.
|
|
setDualListingVertical(VTMarkupItemsTableProvider.class);// Switch orientation back so we don't mess up later tests.
|
|
}
|
|
|
|
@Test
|
|
public void testVersionTrackingMarkupItemsSideBySide() throws Exception {
|
|
|
|
VTMatch match = getMatch("Call_strncpy_s", VTAssociationType.FUNCTION);
|
|
replaceMarkup(match, "00411ab0", "Function Signature");
|
|
addMarkup(match, "00411ad3", "EOL Comment");
|
|
tagMarkup(VTMarkupItemConsideredStatus.IGNORE_DONT_CARE, match, "00411ad7", "EOL Comment");
|
|
tagMarkup(VTMarkupItemConsideredStatus.REJECT, match, "00411ad8", "EOL Comment");
|
|
|
|
selectMatch("Call_strncpy_s");
|
|
|
|
setToolSize(1300, 800);
|
|
|
|
setMarkupTableDivider(70);
|
|
|
|
captureIsolatedProvider(VTMarkupItemsTableProvider.class, 1100, 630);
|
|
}
|
|
|
|
/////////////////////
|
|
// VT_Matches_Table
|
|
/////////////////////
|
|
|
|
@Test
|
|
public void testMatchesTable() throws Exception {
|
|
|
|
setToolSize(1200, 450);
|
|
|
|
selectMatch("Call_strncpy_s");
|
|
|
|
captureIsolatedProvider(VTMatchTableProvider.class, 1200, 400);
|
|
}
|
|
|
|
//////////////////////////////////
|
|
// VT_Related_Associations_Table
|
|
//////////////////////////////////
|
|
|
|
@Test
|
|
public void testOneToManySource() throws Exception {
|
|
|
|
VTMatch match = getMatch("addPerson", VTAssociationType.FUNCTION);
|
|
List<VTMatch> matchesToAccept = new ArrayList<>();
|
|
matchesToAccept.add(match);
|
|
|
|
AcceptMatchTask task = new AcceptMatchTask(controller, matchesToAccept);
|
|
controller.runVTTask(task);
|
|
|
|
vtTestEnv.correlate(new SymbolNameProgramCorrelatorFactory(), null,
|
|
TaskMonitor.DUMMY);
|
|
|
|
sourceAddress = sourceProgram.getAddressFactory().getAddress("0x00411860");
|
|
sourceFunction = sourceProgram.getFunctionManager().getFunctionAt(sourceAddress);
|
|
destinationAddress = destinationProgram.getAddressFactory().getAddress("0x004118c0");
|
|
destinationFunction =
|
|
destinationProgram.getFunctionManager().getFunctionAt(destinationAddress);
|
|
CreateManualMatchTask createMatchTask =
|
|
new CreateManualMatchTask(session, sourceFunction, destinationFunction);
|
|
controller.runVTTask(createMatchTask);
|
|
|
|
waitForBusyTool(vtTool);
|
|
|
|
selectMatch("addPerson");
|
|
|
|
VTSubToolManager toolManager = vtPlugin.getToolManager();
|
|
PluginTool sourceTool = (PluginTool) getInstanceField("sourceTool", toolManager);
|
|
PluginTool destinationTool = (PluginTool) getInstanceField("destinationTool", toolManager);
|
|
assertNotNull(sourceTool);
|
|
assertNotNull(destinationTool);
|
|
|
|
tool = sourceTool;
|
|
setToolSize(1200, 550);
|
|
captureIsolatedProvider(VTMatchSourceTableProvider.class, 800, 240);
|
|
|
|
tool = vtTool;
|
|
}
|
|
|
|
@Test
|
|
public void testOneToManyDestination() throws Exception {
|
|
|
|
VTMatch match = getMatch("addPerson", VTAssociationType.FUNCTION);
|
|
List<VTMatch> matchesToAccept = new ArrayList<>();
|
|
matchesToAccept.add(match);
|
|
|
|
AcceptMatchTask task = new AcceptMatchTask(controller, matchesToAccept);
|
|
controller.runVTTask(task);
|
|
|
|
vtTestEnv.correlate(new SymbolNameProgramCorrelatorFactory(), null,
|
|
TaskMonitor.DUMMY);
|
|
|
|
sourceAddress = sourceProgram.getAddressFactory().getAddress("0x00411860");
|
|
sourceFunction = sourceProgram.getFunctionManager().getFunctionAt(sourceAddress);
|
|
destinationAddress = destinationProgram.getAddressFactory().getAddress("0x004118c0");
|
|
destinationFunction =
|
|
destinationProgram.getFunctionManager().getFunctionAt(destinationAddress);
|
|
CreateManualMatchTask createMatchTask =
|
|
new CreateManualMatchTask(session, sourceFunction, destinationFunction);
|
|
controller.runVTTask(createMatchTask);
|
|
|
|
waitForBusyTool(vtTool);
|
|
|
|
selectMatch("addPerson");
|
|
|
|
VTSubToolManager toolManager = vtPlugin.getToolManager();
|
|
PluginTool sourceTool = (PluginTool) getInstanceField("sourceTool", toolManager);
|
|
PluginTool destinationTool = (PluginTool) getInstanceField("destinationTool", toolManager);
|
|
assertNotNull(sourceTool);
|
|
assertNotNull(destinationTool);
|
|
|
|
tool = destinationTool;
|
|
setToolSize(1200, 550);
|
|
captureIsolatedProvider(VTMatchDestinationTableProvider.class, 800, 220);
|
|
|
|
tool = vtTool;
|
|
}
|
|
|
|
@Test
|
|
public void testVersionTrackingTool() throws Exception {
|
|
|
|
tool = vtTool;
|
|
|
|
hideDualListing(VTMarkupItemsTableProvider.class);
|
|
|
|
setToolSize(1200, 500);
|
|
|
|
VTMatchTableProvider provider = getProvider(VTMatchTableProvider.class);
|
|
setProportionalSplitPaneSize(provider, .6f);
|
|
|
|
// We want the match table and markup items table in the tool.
|
|
// So close the implied matches table provider.
|
|
closeProvider(VTImpliedMatchesTableProvider.class);
|
|
|
|
selectMatch("addPerson");
|
|
|
|
captureWindow();
|
|
|
|
showProvider(VTImpliedMatchesTableProvider.class);
|
|
}
|
|
|
|
private void setProportionalSplitPaneSize(ComponentProvider provider, float size) {
|
|
|
|
SplitPanel split = getSplitPanelFor(provider);
|
|
boolean isLeft = split.isLeft(provider.getComponent());
|
|
float adjustedSize = isLeft ? size : 1 - size;
|
|
runSwing(() -> split.setDividerPosition(adjustedSize));
|
|
}
|
|
|
|
private SplitPanel getSplitPanelFor(ComponentProvider provider) {
|
|
JComponent component = provider.getComponent();
|
|
SplitPanel split = getSplitPanelFor(component);
|
|
assertNotNull("Unable to find Split Pane for " + provider.getName());
|
|
return split;
|
|
}
|
|
|
|
private SplitPanel getSplitPanelFor(Component component) {
|
|
Component parent = component.getParent();
|
|
while (parent != null) {
|
|
parent = parent.getParent();
|
|
if (parent instanceof SplitPanel) {
|
|
return (SplitPanel) parent;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
@Test
|
|
public void testSourceTool() throws Exception {
|
|
|
|
waitForBusyTool(vtTool);
|
|
tool = vtTool;
|
|
|
|
selectMatch("addPerson");
|
|
|
|
VTSubToolManager toolManager = vtPlugin.getToolManager();
|
|
PluginTool sourceTool = (PluginTool) getInstanceField("sourceTool", toolManager);
|
|
PluginTool destinationTool = (PluginTool) getInstanceField("destinationTool", toolManager);
|
|
assertNotNull(sourceTool);
|
|
assertNotNull(destinationTool);
|
|
|
|
tool = sourceTool;
|
|
setToolSize(1200, 550);
|
|
sourceTool.toFront();
|
|
captureToolWindow(1200, 550);
|
|
|
|
tool = vtTool;
|
|
}
|
|
|
|
@Test
|
|
public void testSessionPanel() throws Exception {
|
|
|
|
setupVTWizardSessionPanel();
|
|
captureDialog(700, 500);
|
|
|
|
// Once the panel we want is captured, cancel out of the wizard.
|
|
pressButtonByText(getDialog(), "Cancel");
|
|
}
|
|
|
|
@Test
|
|
public void testPreconditionsPanel() throws Exception {
|
|
|
|
setupVTWizardPreconditionsPanel();
|
|
captureDialog(600, 500);
|
|
|
|
// Once the panel we want is captured, cancel out of the wizard.
|
|
pressButtonByText(getDialog(), "Cancel");
|
|
}
|
|
|
|
@Test
|
|
public void testSummaryPanel() throws Exception {
|
|
setupVTWizardSummaryPanel();
|
|
captureDialog(600, 400);
|
|
|
|
// Once the panel we want is captured, cancel out of the wizard.
|
|
pressButtonByText(getDialog(), "Cancel");
|
|
}
|
|
|
|
@Test
|
|
public void testCorrelatorPanel() throws Exception {
|
|
|
|
setupVTWizardCorrelatorPanel();
|
|
captureDialog(800, 400);
|
|
|
|
// Once the panel we want is captured, cancel out of the wizard.
|
|
pressButtonByText(getDialog(), "Cancel");
|
|
}
|
|
|
|
@Test
|
|
public void testOptionsPanel() throws Exception {
|
|
setupVTWizardOptionsPanel();
|
|
captureDialog(700, 500);
|
|
|
|
// Once the panel we want is captured, cancel out of the wizard.
|
|
pressButtonByText(getDialog(), "Cancel");
|
|
}
|
|
|
|
@Test
|
|
public void testVT_Wizard_AddressSetOptions() throws Exception {
|
|
setupVTWizardAddressSetOptionsPanel();
|
|
captureDialog(600, 400);
|
|
|
|
// Once the panel we want is captured, cancel out of the wizard.
|
|
pressButtonByText(getDialog(), "Cancel");
|
|
}
|
|
|
|
@Test
|
|
public void testVT_Wizard_SelectAddressRanges() throws Exception {
|
|
setupVTWizardSelectAddressRangesPanel();
|
|
captureDialog(600, 600);
|
|
|
|
// Once the panel we want is captured, cancel out of the wizard.
|
|
pressButtonByText(getDialog(), "Cancel");
|
|
}
|
|
|
|
@Test
|
|
public void testVT_Wizard_AddToSession_Summary() throws Exception {
|
|
setupVTWizardAddToSessionPanel();
|
|
captureDialog(600, 400);
|
|
|
|
// Once the panel we want is captured, cancel out of the wizard.
|
|
pressButtonByText(getDialog(), "Cancel");
|
|
}
|
|
|
|
////////////////
|
|
// VT_Workflow
|
|
////////////////
|
|
|
|
@Test
|
|
public void testImpliedMatchExample() throws Exception {
|
|
// We want the match table and implied match table in the tool.
|
|
// So close the markup items table provider.
|
|
closeProvider(VTMarkupItemsTableProvider.class);
|
|
|
|
setToolSize(1200, 250);
|
|
|
|
selectMatch("main");
|
|
|
|
captureToolWindow(1200, 550);
|
|
|
|
// Open the closed provider so that tests that follow this one don't get messed up.
|
|
showProvider(VTMarkupItemsTableProvider.class);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
private void setMarkupTableDivider(final int dividerLocationInPixels) {
|
|
Window window = waitForWindowByTitleContaining("Test Tool");
|
|
assertNotNull(window);
|
|
VTMarkupItemsTableProvider provider =
|
|
waitForComponentProvider(VTMarkupItemsTableProvider.class);
|
|
runSwing(() -> {
|
|
JSplitPane splitPane = (JSplitPane) getInstanceField("splitPane", provider);
|
|
splitPane.setDividerLocation(dividerLocationInPixels);
|
|
});
|
|
waitForSwing();
|
|
}
|
|
|
|
private VTMatch getMatch(String sourceLabel, VTAssociationType matchType) {
|
|
List<VTMatchSet> matchSets = session.getMatchSets();
|
|
for (VTMatchSet vtMatchSet : matchSets) {
|
|
Collection<VTMatch> matches = vtMatchSet.getMatches();
|
|
for (VTMatch vtMatch : matches) {
|
|
VTAssociation association = vtMatch.getAssociation();
|
|
VTAssociationType type = association.getType();
|
|
if (type != matchType) {
|
|
continue;
|
|
}
|
|
Address sourceAddr = association.getSourceAddress();
|
|
SymbolTable symbolTable = sourceProgram.getSymbolTable();
|
|
Symbol primarySymbol = symbolTable.getPrimarySymbol(sourceAddr);
|
|
String name = primarySymbol.getName(false);
|
|
if (name.equals(sourceLabel)) {
|
|
return vtMatch;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private void replaceMarkup(VTMatch match, String markupSourceAddress, String markupType) {
|
|
MatchInfo matchInfo = controller.getMatchInfo(match);
|
|
Collection<VTMarkupItem> appliableMarkupItems =
|
|
matchInfo.getAppliableMarkupItems(TaskMonitor.DUMMY);
|
|
for (VTMarkupItem vtMarkupItem : appliableMarkupItems) {
|
|
Address itemSourceAddress = vtMarkupItem.getSourceAddress();
|
|
VTMarkupType itemMarkupType = vtMarkupItem.getMarkupType();
|
|
if (itemSourceAddress.toString(false).equals(markupSourceAddress) &&
|
|
itemMarkupType.getDisplayName().equals(markupType)) {
|
|
ToolOptions options = new ToolOptions(VTController.VERSION_TRACKING_OPTIONS_NAME);
|
|
AbstractFunctionSignatureMarkupTest.setApplyMarkupOptionsToReplace(options);
|
|
List<VTMarkupItem> markupItems = new ArrayList<>();
|
|
markupItems.add(vtMarkupItem);
|
|
runApplyMarkupTask(markupItems, options);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void addMarkup(VTMatch match, String markupSourceAddress, String markupType) {
|
|
MatchInfo matchInfo = controller.getMatchInfo(match);
|
|
Collection<VTMarkupItem> appliableMarkupItems =
|
|
matchInfo.getAppliableMarkupItems(TaskMonitor.DUMMY);
|
|
for (VTMarkupItem vtMarkupItem : appliableMarkupItems) {
|
|
Address itemSourceAddress = vtMarkupItem.getSourceAddress();
|
|
VTMarkupType itemMarkupType = vtMarkupItem.getMarkupType();
|
|
if (itemSourceAddress.toString(false).equals(markupSourceAddress) &&
|
|
itemMarkupType.getDisplayName().equals(markupType)) {
|
|
ToolOptions options = new ToolOptions(VTController.VERSION_TRACKING_OPTIONS_NAME);
|
|
AbstractFunctionSignatureMarkupTest.setApplyMarkupOptionsToAdd(options);
|
|
List<VTMarkupItem> markupItems = new ArrayList<>();
|
|
markupItems.add(vtMarkupItem);
|
|
runApplyMarkupTask(markupItems, options);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void tagMarkup(VTMarkupItemConsideredStatus status, VTMatch match,
|
|
String markupSourceAddress, String markupType) {
|
|
MatchInfo matchInfo = controller.getMatchInfo(match);
|
|
Collection<VTMarkupItem> appliableMarkupItems =
|
|
matchInfo.getAppliableMarkupItems(TaskMonitor.DUMMY);
|
|
for (VTMarkupItem vtMarkupItem : appliableMarkupItems) {
|
|
Address itemSourceAddress = vtMarkupItem.getSourceAddress();
|
|
VTMarkupType itemMarkupType = vtMarkupItem.getMarkupType();
|
|
if (itemSourceAddress.toString(false).equals(markupSourceAddress) &&
|
|
itemMarkupType.getDisplayName().equals(markupType)) {
|
|
List<VTMarkupItem> markupItems = new ArrayList<>();
|
|
markupItems.add(vtMarkupItem);
|
|
runTagMarkupTask(markupItems, status);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void runApplyMarkupTask(List<VTMarkupItem> markupItems, ToolOptions options) {
|
|
|
|
waitForBusyTool(vtTestEnv.getTool());
|
|
Msg.debug(this, "runTask(): Apply markup item(s)\n\n");
|
|
|
|
ApplyMarkupItemTask task =
|
|
new ApplyMarkupItemTask(controller.getSession(), markupItems, options);
|
|
task.addTaskListener(new TaskListener() {
|
|
@Override
|
|
public void taskCompleted(Task t) {
|
|
controller.refresh();
|
|
}
|
|
|
|
@Override
|
|
public void taskCancelled(Task t) {
|
|
// don't care; nothing to do
|
|
}
|
|
});
|
|
controller.runVTTask(task);
|
|
|
|
waitForSwing();
|
|
destinationProgram.flushEvents();
|
|
Msg.debug(this, "\tdone task: Apply markup item(s)\n\n");
|
|
}
|
|
|
|
private void runTagMarkupTask(List<VTMarkupItem> markupItems,
|
|
VTMarkupItemConsideredStatus status) {
|
|
|
|
waitForBusyTool(vtTestEnv.getTool());
|
|
Msg.debug(this, "runTask(): " + status.name() + " markup item(s)\n\n");
|
|
|
|
TagMarkupItemTask task = new TagMarkupItemTask(session, markupItems, status);
|
|
task.addTaskListener(new TaskListener() {
|
|
@Override
|
|
public void taskCompleted(Task t) {
|
|
controller.refresh();
|
|
}
|
|
|
|
@Override
|
|
public void taskCancelled(Task t) {
|
|
// don't care; nothing to do
|
|
}
|
|
});
|
|
controller.runVTTask(task);
|
|
|
|
waitForSwing();
|
|
destinationProgram.flushEvents();
|
|
Msg.debug(this, "\tdone task: " + status.name() + " markup item(s)\n\n");
|
|
}
|
|
|
|
@SuppressWarnings("unused")
|
|
private boolean selectRow(GhidraTable markupItemsTable,
|
|
VTMarkupItemsTableModel markupItemsTableModel, int sourceAddressColumn,
|
|
String sourceAddressValue, int markupTypeColumn, String markupTypeValue) {
|
|
int rowCount = markupItemsTableModel.getRowCount();
|
|
for (int row = 0; row < rowCount; row++) {
|
|
Object sourceAddressObject = markupItemsTableModel.getValueAt(row, sourceAddressColumn);
|
|
DisplayableListingAddress sourceAddr = (DisplayableListingAddress) sourceAddressObject;
|
|
Object markupTypeObject = markupItemsTableModel.getValueAt(row, markupTypeColumn);
|
|
String markupType = (String) markupTypeObject;
|
|
if (sourceAddressValue.equals(sourceAddr.getDisplayString()) &&
|
|
markupTypeValue.equals(markupType)) {
|
|
markupItemsTable.selectRow(row);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private void selectMatch(final String sourceLabel) {
|
|
waitForSwing();
|
|
Window window = waitForWindowByTitleContaining("Test Tool");
|
|
assertNotNull(window);
|
|
VTMatchTableProvider matchTableProvider =
|
|
waitForComponentProvider(VTMatchTableProvider.class);
|
|
final GhidraTable matchesTable =
|
|
(GhidraTable) getInstanceField("matchesTable", matchTableProvider);
|
|
final TableModel model = matchesTable.getModel();
|
|
int sourceLabelColumn = -1;
|
|
int columnCount = model.getColumnCount();
|
|
for (int i = 0; i < columnCount; i++) {
|
|
String columnName = model.getColumnName(i);
|
|
if (columnName.equals("Source Label")) {
|
|
sourceLabelColumn = i;
|
|
break;
|
|
}
|
|
}
|
|
Assert.assertNotEquals("Couldn't find Source Label column.", -1, sourceLabelColumn);
|
|
|
|
final int column = sourceLabelColumn;
|
|
runSwing(() -> {
|
|
boolean setSelectedRow = false;
|
|
int rowCount = model.getRowCount();
|
|
for (int i = 0; i < rowCount; i++) {
|
|
Object valueObject = model.getValueAt(i, column);
|
|
DisplayableLabel currentSourceLabel = (DisplayableLabel) valueObject;
|
|
if (currentSourceLabel.getDisplayString().equals(sourceLabel)) {
|
|
matchesTable.selectRow(i);
|
|
matchesTable.scrollToSelectedRow();
|
|
setSelectedRow = true;
|
|
break;
|
|
}
|
|
}
|
|
assertEquals("Couldn't select row containing " + sourceLabel + ".", true,
|
|
setSelectedRow);
|
|
});
|
|
waitForSwing();
|
|
}
|
|
|
|
private void hideDualListing(Class<? extends ComponentProvider> clazz) {
|
|
|
|
ComponentProvider provider = getProvider(clazz);
|
|
|
|
dualListingIsVisible(provider);
|
|
|
|
ToggleDockingAction action =
|
|
(ToggleDockingAction) getLocalAction(provider, "Toggle Dual Listing Visibility");
|
|
assertNotNull(action);
|
|
setToggleActionSelected(action, new DefaultActionContext(), false);
|
|
waitForSwing();
|
|
waitForCondition(() -> !dualListingIsVisible(provider));
|
|
}
|
|
|
|
private boolean dualListingIsVisible(ComponentProvider provider) {
|
|
|
|
JComponent component = provider.getComponent();
|
|
Component listingComponent =
|
|
findComponentByName(component, ListingCodeComparisonPanel.NAME);
|
|
if (listingComponent == null) {
|
|
return false; // not in the parent's hierarchy
|
|
}
|
|
|
|
return listingComponent.isShowing();
|
|
}
|
|
|
|
private DockingActionIf setDualListingVertical(Class<? extends ComponentProvider> clazz) {
|
|
|
|
return setDualListingLayout(clazz, true);
|
|
}
|
|
|
|
private DockingActionIf setDualListingHorizontal(Class<? extends ComponentProvider> clazz) {
|
|
|
|
return setDualListingLayout(clazz, false);
|
|
}
|
|
|
|
private DockingActionIf setDualListingLayout(Class<? extends ComponentProvider> clazz,
|
|
boolean vertical) {
|
|
ComponentProvider provider = getProvider(clazz);
|
|
assertNotNull(provider);
|
|
|
|
ToggleDockingAction action =
|
|
(ToggleDockingAction) getLocalAction(provider, "Dual Listing Toggle Orientation");
|
|
assertNotNull(action);
|
|
setToggleActionSelected(action, new DefaultActionContext(), vertical);
|
|
waitForSwing();
|
|
return action;
|
|
}
|
|
|
|
private DockingActionIf toggleDualListingHeader(Class<? extends ComponentProvider> clazz,
|
|
boolean showing) {
|
|
|
|
ComponentProvider provider = getProvider(clazz);
|
|
assertNotNull(provider);
|
|
|
|
ToggleDockingAction action =
|
|
(ToggleDockingAction) getLocalAction(provider, "Dual Listing Toggle Header");
|
|
assertNotNull(action);
|
|
setToggleActionSelected(action, new DefaultActionContext(), showing);
|
|
waitForSwing();
|
|
return action;
|
|
}
|
|
|
|
private void setupVTWizardAddToSessionPanel() throws Exception {
|
|
setupVTWizardSelectAddressRangesPanel();
|
|
pressNextButtonWhenEnabled();
|
|
}
|
|
|
|
private void setupVTWizardSelectAddressRangesPanel() throws Exception {
|
|
setupVTWizardAddressSetOptionsPanel();
|
|
pressNextButtonWhenEnabled();
|
|
|
|
DialogComponentProvider dialog = getDialog();
|
|
LimitAddressSetsPanel panel = findComponent(dialog, LimitAddressSetsPanel.class);
|
|
AddressSetPanel destinationPanel =
|
|
(AddressSetPanel) getInstanceField("destinationPanel", panel);
|
|
ChooseAddressSetEditorPanel choosePanel =
|
|
findComponent(destinationPanel, ChooseAddressSetEditorPanel.class);
|
|
JRadioButton myRangesButton =
|
|
(JRadioButton) getInstanceField("myRangesButton", choosePanel);
|
|
pressButton(myRangesButton);
|
|
}
|
|
|
|
private void setupVTWizardAddressSetOptionsPanel() throws Exception {
|
|
setupVTWizardOptionsPanel();
|
|
pressNextButtonWhenEnabled();
|
|
|
|
DialogComponentProvider dialog = getDialog();
|
|
AddressSetOptionsPanel panel = findComponent(dialog, AddressSetOptionsPanel.class);
|
|
JCheckBox showAddressSetPanelsCheckbox =
|
|
(JCheckBox) getInstanceField("showAddressSetPanelsCheckbox", panel);
|
|
showAddressSetPanelsCheckbox.setSelected(true);
|
|
}
|
|
|
|
private void setupVTWizardOptionsPanel() throws Exception {
|
|
setupVTWizardCorrelatorPanel();
|
|
DialogComponentProvider dialog = getDialog();
|
|
CorrelatorPanel correlatorPanel = findComponent(dialog, CorrelatorPanel.class);
|
|
VTProgramTableCorrelatorModel model =
|
|
(VTProgramTableCorrelatorModel) getInstanceField("model", correlatorPanel);
|
|
model.setValueAt(true, 1, 0);// Set "Exact Function Bytes Match" to selected.
|
|
model.fireTableDataChanged();
|
|
waitForSwing();
|
|
pressNextButtonWhenEnabled();
|
|
}
|
|
|
|
private void setupVTWizardCorrelatorPanel() throws Exception {
|
|
tool = vtTool;
|
|
DockingActionIf dockingAction = getAction(vtPlugin, "Add To Session");
|
|
performAction(dockingAction, false);
|
|
waitForSwing();
|
|
}
|
|
|
|
private void setupVTWizardSummaryPanel() throws Exception {
|
|
setupVTWizardPreconditionsPanel();
|
|
pressNextButtonWhenEnabled();
|
|
}
|
|
|
|
private void tryToWaitForNextButtonToEnable() {
|
|
Container container = getDialog().getComponent();
|
|
String buttonText = "Next >>";
|
|
AbstractButton button = findAbstractButtonByText(container, buttonText);
|
|
for (int i = 0; i < 100; i++) {
|
|
if (button.isEnabled()) {
|
|
break;
|
|
}
|
|
sleep(20);
|
|
}
|
|
}
|
|
|
|
private void pressNextButtonWhenEnabled() throws UsrException {
|
|
Container container = getDialog().getComponent();
|
|
String buttonText = "Next >>";
|
|
AbstractButton button = findAbstractButtonByText(container, buttonText);
|
|
for (int i = 0; i < 100; i++) {
|
|
if (button.isEnabled()) {
|
|
break;
|
|
}
|
|
sleep(20);
|
|
}
|
|
if (button == null) {
|
|
throw new UsrException("Couldn't find button " + buttonText + ".");
|
|
}
|
|
if (!button.isShowing()) {
|
|
throw new UsrException("Button " + buttonText + " is not showing.");
|
|
}
|
|
if (!button.isEnabled()) {
|
|
throw new UsrException("Button " + buttonText + " is not enabled.");
|
|
}
|
|
pressButton(button, true);
|
|
waitForSwing();
|
|
}
|
|
|
|
private void setupVTWizardPreconditionsPanel() throws UsrException, FileNotFoundException {
|
|
setupVTWizardSessionPanel();
|
|
pressNextButtonWhenEnabled();
|
|
pressButtonByText(getDialog(), "Run Precondition Checks", true);
|
|
waitForBusyTool(vtTool);
|
|
tryToWaitForNextButtonToEnable();
|
|
waitForSwing();
|
|
}
|
|
|
|
private void setupVTWizardSessionPanel() throws FileNotFoundException {
|
|
vtTestEnv.restoreProgram("VersionTracking/WallaceSrc");
|
|
vtTestEnv.restoreProgram("VersionTracking/WallaceVersion2");
|
|
tool = vtTool;
|
|
DockingActionIf dockingAction = getAction(vtPlugin, "Create New Session");
|
|
performAction(dockingAction, false);
|
|
pressButtonByText(getDialog(), "Yes");
|
|
pressButtonByText(getDialog(), "Don't Save");
|
|
|
|
JComponent dialogComponent = getDialog().getComponent();
|
|
// Fill in the Version Tracking Wizard panel.
|
|
|
|
// Set the Source
|
|
chooseProjectFile(dialogComponent, "SOURCE_BUTTON",
|
|
new String[] { "git_DevTestProject", "WallaceSrc" });
|
|
|
|
// Set the Destination
|
|
chooseProjectFile(dialogComponent, "DESTINATION_BUTTON",
|
|
new String[] { "git_DevTestProject", "WallaceVersion2" });
|
|
waitForSwing();
|
|
}
|
|
|
|
private void chooseProjectFile(JComponent dialogComponent, String buttonName,
|
|
String[] treePath) {
|
|
pressButtonByName(dialogComponent, buttonName, false);
|
|
DataTreeDialog dataTreeDialog = (DataTreeDialog) getDialog(DataTreeDialog.class);
|
|
ProjectDataTreePanel treePanel =
|
|
(ProjectDataTreePanel) getInstanceField("treePanel", dataTreeDialog);
|
|
DataTree tree = (DataTree) getInstanceField("tree", treePanel);
|
|
assertNotNull(tree);
|
|
selectPath(tree, treePath);
|
|
pressButtonByText(dataTreeDialog, "OK");
|
|
}
|
|
}
|