/* ### * 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.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.swing.*; import org.junit.Assert; import org.junit.Test; import docking.DialogComponentProvider; import docking.options.editor.DateEditor; import docking.options.editor.OptionsDialog; import docking.widgets.OptionDialog; import docking.widgets.tree.GTree; import docking.widgets.tree.GTreeNode; import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.plugin.core.codebrowser.CodeViewerProvider; import ghidra.app.plugin.core.datamgr.DataTypesProvider; import ghidra.app.plugin.core.progmgr.MultiTabPlugin; import ghidra.app.services.ProgramManager; import ghidra.app.util.dialog.CheckoutDialog; import ghidra.framework.data.CheckinHandler; import ghidra.framework.main.FrontEndTool; import ghidra.framework.main.OpenVersionedFileDialog; import ghidra.framework.model.*; import ghidra.framework.remote.User; import ghidra.program.model.address.*; import ghidra.program.model.listing.Program; import ghidra.program.model.symbol.SourceType; import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskLauncher; import ghidra.util.task.TaskMonitor; public class ProgramManagerPluginScreenShots extends GhidraScreenShotGenerator implements CheckinHandler { private String checkinComment; private boolean keepCheckedOut = true; public ProgramManagerPluginScreenShots() { super(); } @Test public void testClosedTab() throws Exception { createAndOpenPrograms(2, 1); closeProvider(DataTypesProvider.class); captureToolWindow(900, 400); drawOval(Palette.PURPLE, new Rectangle(280, 92, 190, 60), 8); } @Test public void testEditDate() { DateEditor dateEditor = new DateEditor(); Component datePanel = dateEditor.getCustomEditor(); final JButton button = (JButton) getInstanceField("browseButton", datePanel); runSwing(() -> pressButton(button), false); captureDialog(-1, -1);// Let is keep its size, lest we get a bunch of "..." } @Test public void testFileNotCheckedOut() { User user = new User("User 1", User.WRITE); CheckoutDialog checkoutDialog = new CheckoutDialog(program.getDomainFile(), user); showDialogWithoutBlocking(tool, checkoutDialog); captureDialog(); } @Test public void testFrontEnd3() throws Exception { createAndOpenPrograms(3, 1); tool.setConfigChanged(false); env.closeTool(tool); FrontEndTool frontEndTool = getFrontEndTool(); captureWindow(frontEndTool.getActiveWindow(), 500, 500); } @Test public void testFrontEndWithProgram() throws Exception { createAndOpenPrograms(3, 1); tool.setConfigChanged(false); FrontEndTool frontEndTool = getFrontEndTool(); captureWindow(frontEndTool.getActiveWindow(), 500, 500); } @Test public void testOpenHistory() throws Exception { Project project = env.getProject(); ProjectData projectData = project.getProjectData(); projectData.getRootFolder() .createFile("WinHelloCpp.exe", program, TaskMonitor.DUMMY); DomainFile df = program.getDomainFile(); addItemToVersionControl(df, "Added to Version Control", true); // Make change Program p = (Program) df.getDomainObject(this, false, false, null); changeProgram(p, "aaa"); checkinComment = "Version 2"; keepCheckedOut = true; assertTrue(df.canCheckin()); df.checkin(this, null); changeProgram(p, "bbb"); checkinComment = "Version 3"; keepCheckedOut = true; assertTrue(df.canCheckin()); df.checkin(this, null); p.release(this); performAction("Open File", "ProgramManagerPlugin", false); final OpenVersionedFileDialog dialog = (OpenVersionedFileDialog) getDialog(); waitForSwing(); Object treePanel = getInstanceField("treePanel", dialog); final GTree tree = (GTree) getInstanceField("tree", treePanel); GTreeNode rootNode = tree.getViewRoot(); GTreeNode child = rootNode.getChild(0); tree.setSelectedNode(child); assertNotNull(dialog); runSwing(() -> invokeInstanceMethod("advancedButtonCallback", dialog)); captureDialog(850, 400); closeAllWindows(); } @Test public void testOpenProgram() throws Exception { createAndOpenPrograms(3, 1); performAction("Open File", "ProgramManagerPlugin", false); captureDialog(500, 400); closeAllWindows(); } @Test public void testOpenProgramMenu() throws Exception { createAndOpenPrograms(3, 1); performAction("Open File", "ProgramManagerPlugin", false); waitForSwing(); DialogComponentProvider dialog = getDialog(); Object treePanel = getInstanceField("treePanel", dialog); GTree tree = (GTree) getInstanceField("tree", treePanel); JTree jTree = (JTree) getInstanceField("tree", tree); Rectangle rowBounds = jTree.getRowBounds(1); waitForTree(tree); rightClick(jTree, rowBounds.x + 25, rowBounds.y + 10); waitForSwing(); captureDialog(); closeAllWindows(); } @Test public void testProgramOptionsDialog() { performAction("Program Options", "ProgramManagerPlugin", false); OptionsDialog dialog = (OptionsDialog) getDialog(); Object optionsPanel = getInstanceField("panel", dialog); GTree tree = (GTree) getInstanceField("gTree", optionsPanel); GTreeNode rootNode = tree.getViewRoot(); GTreeNode child = rootNode.getChild("Program Information"); tree.setSelectedNode(child); waitForTree(tree); waitForSwing(); captureDialog(); } @Test public void testProgramTabs_No_Hidden() throws Exception { createAndOpenPrograms(4, 2); setToolSize(800, 400); goToListing(0x04002ba); captureIsolatedProvider(CodeViewerProvider.class, 600, 350); } @Test public void testProgramTabs_With_Hidden_Go_to_Program() throws Exception { CodeViewerProvider provider = getProvider(CodeViewerProvider.class); moveProviderToItsOwnWindow(provider); createAndOpenPrograms(6, 2); goToListing(0x04002ba); Window window = windowForComponent(provider.getComponent()); setWindowSize(window, 600, 350); waitForSwing(); performAction("Go To Program", "MultiTabPlugin", true); captureProviderWithScreenShot(provider); } @Test public void testProgramTabs_With_Hidden_More_Button() throws Exception { CodeViewerProvider provider = getProvider(CodeViewerProvider.class); moveProviderToItsOwnWindow(provider); Window window = windowForComponent(provider.getComponent()); setWindowSize(window, 600, 350); waitForSwing(); createAndOpenPrograms(6, 3); captureProvider(CodeViewerProvider.class); drawOval(Palette.PURPLE, new Rectangle(440, 16, 70, 50), 8); } @Test public void testProgramTabs_With_Hidden_Popup_Window() throws Exception { CodeViewerProvider provider = getProvider(CodeViewerProvider.class); moveProviderToItsOwnWindow(provider); createAndOpenPrograms(6, 2); goToListing(0x04002ba); Window window = windowForComponent(provider.getComponent()); setWindowSize(window, 600, 350); waitForSwing(); MultiTabPlugin plugin = getPlugin(tool, MultiTabPlugin.class); Object tabPanel = getInstanceField("tabPanel", plugin); JLabel label = (JLabel) getInstanceField("showHiddenListLabel", tabPanel); leftClick(label, 5, 5); waitForSwing(); Component popupDialog = (Component) getInstanceField("listWindow", tabPanel); Component dockableComponent = getDockableComponent(provider.getComponent()); captureComponents(Arrays.asList(dockableComponent, popupDialog)); } @Test public void testProgramTabs_With_Highlighted_Tab() throws Exception { CodeViewerProvider provider = getProvider(CodeViewerProvider.class); moveProviderToItsOwnWindow(provider); Window window = windowForComponent(provider.getComponent()); setWindowSize(window, 600, 350); waitForSwing(); createAndOpenPrograms(6, 1); runSwing(() -> { MultiTabPlugin plugin = getPlugin(tool, MultiTabPlugin.class); invokeInstanceMethod("highlightNextProgram", plugin, new Class[] { boolean.class }, new Object[] { true }); }); captureProvider(CodeViewerProvider.class); drawOval(Palette.PURPLE, new Rectangle(221, 16, 140, 50), 8); } @Test public void testSaveProgram() { runSwing(() -> OptionDialog.showOptionDialog(tool.getToolFrame(), "Save Program?", "program1 has changed. Do you want to save it?", "&Save", "Do&n't Save", OptionDialog.QUESTION_MESSAGE), false); captureDialog(); } @Test public void testSaveProgramAs() throws Exception { Program p = createAndOpenPrograms(4, 0); changeProgram(p, "Hey"); performAction("Save As File", "ProgramManagerPlugin", false); captureDialog(300, 300); pressButtonOnDialog("Cancel"); } @Test public void testTabs() throws Exception { createAndOpenPrograms(2, 1); goToListing(0x04002ba); captureIsolatedProvider(CodeViewerProvider.class, 600, 230); } private Program createAndOpenPrograms(int count, int currentProgramIndex) throws Exception { program = env.getProgram("WinHelloCPP.exe"); CodeViewerProvider provider = getProvider(CodeViewerProvider.class); Project project = env.getProject(); ProjectData projectData = project.getProjectData(); List list = new ArrayList<>(); for (int i = 0; i < count; i++) { String programName = "Program" + (i + 1) + ".exe"; list.add(projectData.getRootFolder() .createFile(programName, program, TaskMonitor.DUMMY)); } program.flushEvents(); ProgramManager service = tool.getService(ProgramManager.class); service.closeAllPrograms(true); List programs = new ArrayList<>(); for (DomainFile domainFile : list) { programs.add(service.openProgram(domainFile)); } service.setCurrentProgram(programs.get(currentProgramIndex)); return programs.get(currentProgramIndex); } private void changeProgram(Program p, String labelName) { int txId = p.startTransaction("create symbol"); try { p.getSymbolTable().createLabel(getAddr(p, 0), labelName, SourceType.USER_DEFINED); } catch (Exception e) { Assert.fail("Unexpected Exception creating symbol"); } finally { p.endTransaction(txId, true); } try { p.save(null, null); } catch (Exception e) { Assert.fail("Unexpected Exception saving Exception"); } } private void addItemToVersionControl(DomainFile domainFile, String comment, boolean keepItCheckedOut) throws Exception { TaskLauncher.launchModal(comment, () -> { try { domainFile.addToVersionControl(comment, keepItCheckedOut, TaskMonitor.DUMMY); } catch (CancelledException | IOException e) { throw new RuntimeException(e); } }); waitForSwing(); } private Address getAddr(Program p, long offset) { AddressFactory addrMap = p.getAddressFactory(); AddressSpace space = addrMap.getDefaultAddressSpace(); return space.getAddress(offset); } @Override public String getComment() { return checkinComment; } @Override public boolean keepCheckedOut() { return keepCheckedOut; } @Override public boolean createKeepFile() throws CancelledException { return false; } }