diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProviderObjectTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProviderObjectTest.java index 18a8209827..6ebabf53af 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProviderObjectTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProviderObjectTest.java @@ -17,12 +17,16 @@ package ghidra.app.plugin.core.debug.gui.breakpoint; import java.io.IOException; +import org.junit.experimental.categories.Category; + +import generic.test.category.NightlyCategory; import ghidra.dbg.target.schema.SchemaContext; import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName; import ghidra.dbg.target.schema.XmlSchemaContext; import ghidra.trace.model.Trace; import ghidra.util.database.UndoableTransaction; +@Category(NightlyCategory.class) public class DebuggerBreakpointsProviderObjectTest extends DebuggerBreakpointsProviderTest { protected SchemaContext ctx; diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/copying/DebuggerCopyActionsPluginTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/copying/DebuggerCopyActionsPluginTest.java index 41245fe016..41a2ba9dc7 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/copying/DebuggerCopyActionsPluginTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/copying/DebuggerCopyActionsPluginTest.java @@ -23,11 +23,13 @@ import java.util.concurrent.TimeUnit; import org.junit.Before; import org.junit.Test; +import org.junit.experimental.categories.Category; import com.google.common.collect.Range; import docking.action.DockingActionIf; import generic.Unique; +import generic.test.category.NightlyCategory; import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest; import ghidra.app.plugin.core.debug.gui.action.AutoReadMemorySpec; import ghidra.app.plugin.core.debug.gui.action.NoneAutoReadMemorySpec; @@ -50,6 +52,7 @@ import ghidra.trace.model.TraceLocation; import ghidra.trace.model.memory.TraceMemoryFlag; import ghidra.util.database.UndoableTransaction; +@Category(NightlyCategory.class) public class DebuggerCopyActionsPluginTest extends AbstractGhidraHeadedDebuggerGUITest { DebuggerCopyActionsPlugin copyActionsPlugin; @@ -136,8 +139,8 @@ public class DebuggerCopyActionsPluginTest extends AbstractGhidraHeadedDebuggerG try (UndoableTransaction tid = UndoableTransaction.start(program, "Add blocks", true)) { program.getMemory() - .createInitializedBlock(".text", tb.addr(stSpace, 0x00400000), 0x8000, - (byte) 0, monitor, false); + .createInitializedBlock(".text", tb.addr(stSpace, 0x00400000), 0x8000, (byte) 0, + monitor, false); program.getMemory() .createInitializedBlock(".text2", tb.addr(stSpace, 0x00408000), 0x8000, (byte) 0, monitor, false); @@ -145,8 +148,8 @@ public class DebuggerCopyActionsPluginTest extends AbstractGhidraHeadedDebuggerG try (UndoableTransaction tid = tb.startTransaction()) { DBTraceMemoryManager mm = tb.trace.getMemoryManager(); - mm.createRegion(".text", 0, tb.range(0x00400000, 0x0040ffff), - TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); + mm.createRegion(".text", 0, tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, + TraceMemoryFlag.EXECUTE); mm.putBytes(0, tb.addr(0x00401234), tb.buf(1, 2, 3, 4)); // This region should be excluded, since it cannot be mapped identically into 32-bits @@ -163,9 +166,7 @@ public class DebuggerCopyActionsPluginTest extends AbstractGhidraHeadedDebuggerG traceManager.activateTrace(tb.trace); assertDisabled(copyActionsPlugin.actionCopyIntoCurrentProgram); - select(tb.set( - tb.range(0x00400000, 0x0040ffff), - tb.range(0x7fff00400000L, 0x7fff0040ffffL), + select(tb.set(tb.range(0x00400000, 0x0040ffff), tb.range(0x7fff00400000L, 0x7fff0040ffffL), tb.range(0xfffff000L, 0x100000fffL))); performEnabledAction(copyActionsPlugin.actionCopyIntoCurrentProgram); diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/interpreters/DebuggerInterpreterPluginTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/interpreters/DebuggerInterpreterPluginTest.java index b8ea98068d..ba64b86b23 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/interpreters/DebuggerInterpreterPluginTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/interpreters/DebuggerInterpreterPluginTest.java @@ -24,13 +24,16 @@ import java.util.Map; import org.junit.Before; import org.junit.Test; +import org.junit.experimental.categories.Category; +import generic.test.category.NightlyCategory; import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest; import ghidra.app.plugin.core.interpreter.InterpreterComponentProvider; import ghidra.dbg.model.TestTargetInterpreter.ExecuteCall; import ghidra.dbg.target.TargetConsole.Channel; import ghidra.dbg.testutil.DebuggerModelTestUtils; +@Category(NightlyCategory.class) public class DebuggerInterpreterPluginTest extends AbstractGhidraHeadedDebuggerGUITest implements DebuggerModelTestUtils { private DebuggerInterpreterPlugin interpreterPlugin; @@ -124,8 +127,7 @@ public class DebuggerInterpreterPluginTest extends AbstractGhidraHeadedDebuggerG InterpreterComponentProvider interpreter = waitForComponentProvider(InterpreterComponentProvider.class); - mb.testModel.session.changeAttributes(List.of( - "Interpreter" // + mb.testModel.session.changeAttributes(List.of("Interpreter" // ), Map.of(), "Invalidate interpreter"); waitForSwing(); @@ -142,8 +144,7 @@ public class DebuggerInterpreterPluginTest extends AbstractGhidraHeadedDebuggerG waitForComponentProvider(InterpreterComponentProvider.class); conn.setPinned(true); - mb.testModel.session.changeAttributes(List.of( - "Interpreter" // + mb.testModel.session.changeAttributes(List.of("Interpreter" // ), Map.of(), "Invalidate interpreter"); waitForSwing(); diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProviderTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProviderTest.java index 7e5d17ff4e..74de4f9dc1 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProviderTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProviderTest.java @@ -15,7 +15,7 @@ */ package ghidra.app.plugin.core.debug.gui.listing; -import static ghidra.lifecycle.Unfinished.TODO; +import static ghidra.lifecycle.Unfinished.*; import static org.junit.Assert.*; import java.awt.Color; @@ -26,12 +26,14 @@ import java.util.Arrays; import java.util.Set; import org.junit.*; +import org.junit.experimental.categories.Category; import com.google.common.collect.Range; import docking.menu.ActionState; import docking.menu.MultiStateDockingAction; import docking.widgets.EventTrigger; +import generic.test.category.NightlyCategory; import ghidra.app.plugin.core.debug.DebuggerCoordinates; import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest; import ghidra.app.plugin.core.debug.gui.DebuggerResources; @@ -65,6 +67,7 @@ import ghidra.util.exception.CancelledException; import ghidra.util.exception.VersionException; import ghidra.util.task.TaskMonitor; +@Category(NightlyCategory.class) public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUITest { protected DebuggerListingPlugin listingPlugin; @@ -233,8 +236,9 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI createAndOpenTrace(); TraceThread thread1; TraceThread thread2; - DebuggerListingProvider extraProvider = SwingExecutorService.INSTANCE.submit( - () -> listingPlugin.createListingIfMissing(trackPc, true)).get(); + DebuggerListingProvider extraProvider = SwingExecutorService.INSTANCE + .submit(() -> listingPlugin.createListingIfMissing(trackPc, true)) + .get(); try (UndoableTransaction tid = tb.startTransaction()) { DBTraceMemoryManager memory = tb.trace.getMemoryManager(); memory.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff), @@ -301,8 +305,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI } @Test - public void testFollowsCurrentTraceOnTraceChangeWithoutRegisterTracking() - throws Exception { + public void testFollowsCurrentTraceOnTraceChangeWithoutRegisterTracking() throws Exception { listingProvider.setTrackingSpec(trackNone); try ( // ToyDBTraceBuilder b1 = @@ -358,8 +361,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI } @Test - public void testFollowsCurrentThreadOnThreadChangeWithoutRegisterTracking() - throws Exception { + public void testFollowsCurrentThreadOnThreadChangeWithoutRegisterTracking() throws Exception { listingProvider.setTrackingSpec(trackNone); try ( // ToyDBTraceBuilder b1 = @@ -616,8 +618,8 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI // While we're here, ensure static view didn't track anywhere assertEquals(cur, codeViewer.getCurrentLocation().getAddress()); - assertListingBackgroundAt(Color.WHITE, - codeViewer.getListingPanel(), ss.getAddress(0x00601234), 0); + assertListingBackgroundAt(Color.WHITE, codeViewer.getListingPanel(), + ss.getAddress(0x00601234), 0); } @Test @@ -703,8 +705,8 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI assertListingBackgroundAt(DebuggerResources.DEFAULT_COLOR_BACKGROUND_STALE, listingProvider.getListingPanel(), tb.addr(0x00401233), 0); - assertListingBackgroundAt(Color.WHITE, - listingProvider.getListingPanel(), tb.addr(0x00401234), 0); + assertListingBackgroundAt(Color.WHITE, listingProvider.getListingPanel(), + tb.addr(0x00401234), 0); assertListingBackgroundAt(DebuggerResources.DEFAULT_COLOR_BACKGROUND_ERROR, listingProvider.getListingPanel(), tb.addr(0x00401235), 0); } @@ -717,8 +719,8 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI assertEquals(traceManager.getCurrentView(), listingProvider.getProgram()); assertEquals("(nowhere)", listingProvider.locationLabel.getText()); - DebuggerListingProvider extraProvider = runSwing( - () -> listingPlugin.createListingIfMissing(trackNone, false)); + DebuggerListingProvider extraProvider = + runSwing(() -> listingPlugin.createListingIfMissing(trackNone, false)); waitForSwing(); assertEquals(traceManager.getCurrentView(), extraProvider.getProgram()); assertEquals("(nowhere)", extraProvider.locationLabel.getText()); @@ -765,18 +767,18 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI assertTrue(listingProvider.actionGoTo.isEnabled()); performAction(listingProvider.actionGoTo, false); - DebuggerGoToDialog dialog = waitForDialogComponent(DebuggerGoToDialog.class); + DebuggerGoToDialog dialog1 = waitForDialogComponent(DebuggerGoToDialog.class); - dialog.setExpression("r0"); - dialog.okCallback(); + dialog1.setExpression("r0"); + runSwing(() -> dialog1.okCallback()); waitForPass( () -> assertEquals(tb.addr(0x00401234), listingProvider.getLocation().getAddress())); performAction(listingProvider.actionGoTo, false); - dialog = waitForDialogComponent(DebuggerGoToDialog.class); - dialog.setExpression("*:4 r0"); - dialog.okCallback(); + DebuggerGoToDialog dialog2 = waitForDialogComponent(DebuggerGoToDialog.class); + dialog2.setExpression("*:4 r0"); + runSwing(() -> dialog2.okCallback()); waitForPass( () -> assertEquals(tb.addr(0x00404321), listingProvider.getLocation().getAddress())); @@ -844,8 +846,8 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI 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); + .createInitializedBlock(".text", ss.getAddress(0x00600000), 0x10000, (byte) 0, + monitor, false); } try (UndoableTransaction tid = tb.startTransaction()) { DBTraceMemoryManager memory = tb.trace.getMemoryManager(); @@ -905,8 +907,8 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI traceManager.activateThread(thread1); // NOTE: Action does not exist for main dynamic listing - DebuggerListingProvider extraProvider = runSwing( - () -> listingPlugin.createListingIfMissing(trackNone, true)); + DebuggerListingProvider extraProvider = + runSwing(() -> listingPlugin.createListingIfMissing(trackNone, true)); waitForSwing(); assertTrue(extraProvider.actionFollowsCurrentThread.isEnabled()); assertTrue(extraProvider.actionFollowsCurrentThread.isSelected()); @@ -1032,8 +1034,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI assertEquals(readVisROOnce, listingProvider.getAutoReadMemorySpec()); assertEquals(readVisROOnce, listingProvider.actionAutoReadMemory.getCurrentUserData()); - listingProvider.actionAutoReadMemory - .setCurrentActionStateByUserData(readNone); + listingProvider.actionAutoReadMemory.setCurrentActionStateByUserData(readNone); waitForSwing(); assertEquals(readNone, listingProvider.getAutoReadMemorySpec()); assertEquals(readNone, listingProvider.actionAutoReadMemory.getCurrentUserData()); @@ -1061,8 +1062,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI Set.of(TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE)); TraceModule bin = tb.trace.getModuleManager() - .addLoadedModule("/bin/bash", "/bin/bash", - tb.range(0x00400000, 0x0041ffff), 0); + .addLoadedModule("/bin/bash", "/bin/bash", tb.range(0x00400000, 0x0041ffff), 0); bin.addSection("bash[.text]", tb.range(0x00400000, 0x0040ffff)); traceManager.activateTrace(tb.trace); @@ -1092,8 +1092,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI Set.of(TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE)); tb.trace.getModuleManager() - .addLoadedModule("/bin/bash", "/bin/bash", - tb.range(0x00400000, 0x0041ffff), 0); + .addLoadedModule("/bin/bash", "/bin/bash", tb.range(0x00400000, 0x0041ffff), 0); traceManager.activateTrace(tb.trace); } @@ -1128,8 +1127,8 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI TraceModule modExe; try (UndoableTransaction tid = tb.startTransaction()) { modExe = tb.trace.getModuleManager() - .addModule("modExe", "modExe", - tb.range(0x55550000, 0x555501ff), Range.atLeast(0L)); + .addModule("modExe", "modExe", tb.range(0x55550000, 0x555501ff), + Range.atLeast(0L)); } waitForDomainObject(tb.trace); waitForPass(() -> assertEquals("modExe", listingProvider.locationLabel.getText())); @@ -1157,19 +1156,17 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI .createRegion(".text", 0, tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); thread1 = tb.getOrAddThread("Thread1", 0); - tb.exec(0, 0, thread1, java.util.List.of( - "RIP = 0x00400000;")); + tb.exec(0, 0, thread1, java.util.List.of("RIP = 0x00400000;")); } TraceThread thread2; try (UndoableTransaction tid = tb2.startTransaction()) { tb2.trace.getTimeManager().createSnapshot("First"); tb2.trace.getMemoryManager() - .createRegion(".text", 0, tb2.range(0x200, 0x3ff), - TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); + .createRegion(".text", 0, tb2.range(0x200, 0x3ff), TraceMemoryFlag.READ, + TraceMemoryFlag.EXECUTE); thread2 = tb2.getOrAddThread("Thread2", 0); - tb2.exec(0, 0, thread2, java.util.List.of( - "PC = 0x100;")); + tb2.exec(0, 0, thread2, java.util.List.of("PC = 0x100;")); } traceManager.openTrace(tb.trace); diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProviderObjectTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProviderObjectTest.java index 3f24e80448..3eadcbce53 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProviderObjectTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProviderObjectTest.java @@ -17,11 +17,15 @@ package ghidra.app.plugin.core.debug.gui.memory; import java.io.IOException; +import org.junit.experimental.categories.Category; + +import generic.test.category.NightlyCategory; import ghidra.dbg.target.schema.SchemaContext; import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName; import ghidra.dbg.target.schema.XmlSchemaContext; import ghidra.util.database.UndoableTransaction; +@Category(NightlyCategory.class) public class DebuggerRegionsProviderObjectTest extends DebuggerRegionsProviderTest { protected SchemaContext ctx; diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProviderTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProviderTest.java index 02600cdd09..c72088ccf6 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProviderTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerRegionsProviderTest.java @@ -21,10 +21,12 @@ import java.util.*; import org.junit.Before; import org.junit.Test; +import org.junit.experimental.categories.Category; import com.google.common.collect.Range; import generic.Unique; +import generic.test.category.NightlyCategory; import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest; import ghidra.app.plugin.core.debug.gui.DebuggerBlockChooserDialog; import ghidra.app.plugin.core.debug.gui.DebuggerBlockChooserDialog.MemoryBlockRow; @@ -41,6 +43,7 @@ import ghidra.trace.model.memory.*; import ghidra.trace.model.modules.TraceStaticMapping; import ghidra.util.database.UndoableTransaction; +@Category(NightlyCategory.class) public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUITest { DebuggerRegionsProvider provider; @@ -105,8 +108,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUI try (UndoableTransaction tid = tb.startTransaction()) { TraceMemoryManager mm = tb.trace.getMemoryManager(); region = mm.addRegion("Memory[bin:.text]", Range.atLeast(0L), - tb.range(0x00400000, 0x0040ffff), - TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); } traceManager.openTrace(tb.trace); @@ -134,8 +136,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUI try (UndoableTransaction tid = tb.startTransaction()) { TraceMemoryManager mm = tb.trace.getMemoryManager(); region = mm.addRegion("Memory[bin:.text]", Range.atLeast(0L), - tb.range(0x00400000, 0x0040ffff), - TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); } waitForSwing(); @@ -152,8 +153,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUI try (UndoableTransaction tid = tb.startTransaction()) { TraceMemoryManager mm = tb.trace.getMemoryManager(); region = mm.addRegion("Memory[bin:.text]", Range.atLeast(0L), - tb.range(0x00400000, 0x0040ffff), - TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); } traceManager.openTrace(tb.trace); @@ -222,8 +222,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUI try (UndoableTransaction tid = tb.startTransaction()) { TraceMemoryManager mm = tb.trace.getMemoryManager(); region = mm.addRegion("Memory[bin:.text]", Range.atLeast(0L), - tb.range(0x00400000, 0x0040ffff), - TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); } traceManager.openTrace(tb.trace); @@ -338,8 +337,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUI try (UndoableTransaction tid = tb.startTransaction()) { TraceMemoryManager mm = tb.trace.getMemoryManager(); region = mm.addRegion("Memory[bin:.text]", Range.atLeast(0L), - tb.range(0x00400000, 0x0040ffff), - TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); } traceManager.openTrace(tb.trace); @@ -371,8 +369,7 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerGUI try (UndoableTransaction tid = tb.startTransaction()) { TraceMemoryManager mm = tb.trace.getMemoryManager(); region = mm.addRegion("Memory[bin:.text]", Range.atLeast(0L), - tb.range(0x00400000, 0x0040ffff), - TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); + tb.range(0x00400000, 0x0040ffff), TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE); } traceManager.openTrace(tb.trace); diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesProviderObjectTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesProviderObjectTest.java index cfcb07b198..4018e70ea0 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesProviderObjectTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesProviderObjectTest.java @@ -17,12 +17,16 @@ package ghidra.app.plugin.core.debug.gui.modules; import java.io.IOException; +import org.junit.experimental.categories.Category; + +import generic.test.category.NightlyCategory; import ghidra.dbg.target.schema.SchemaContext; import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName; -import ghidra.trace.model.Trace; import ghidra.dbg.target.schema.XmlSchemaContext; +import ghidra.trace.model.Trace; import ghidra.util.database.UndoableTransaction; +@Category(NightlyCategory.class) public class DebuggerModulesProviderObjectTest extends DebuggerModulesProviderTest { protected SchemaContext ctx; diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerStaticMappingProviderTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerStaticMappingProviderTest.java index 19370398ac..1869631e4a 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerStaticMappingProviderTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerStaticMappingProviderTest.java @@ -23,10 +23,12 @@ import java.util.*; import org.junit.Before; import org.junit.Test; +import org.junit.experimental.categories.Category; import com.google.common.collect.Range; import generic.Unique; +import generic.test.category.NightlyCategory; import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin; import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest; import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingPlugin; @@ -41,6 +43,7 @@ import ghidra.trace.model.modules.TraceStaticMappingManager; import ghidra.util.database.UndoableTransaction; import ghidra.util.task.TaskMonitor; +@Category(NightlyCategory.class) public class DebuggerStaticMappingProviderTest extends AbstractGhidraHeadedDebuggerGUITest { protected DebuggerStaticMappingPlugin mappingsPlugin; protected DebuggerStaticMappingProvider mappingsProvider; diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/thread/DebuggerThreadsProviderObjectTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/thread/DebuggerThreadsProviderObjectTest.java index ae9d9487eb..9fd75693d0 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/thread/DebuggerThreadsProviderObjectTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/thread/DebuggerThreadsProviderObjectTest.java @@ -17,12 +17,16 @@ package ghidra.app.plugin.core.debug.gui.thread; import java.io.IOException; +import org.junit.experimental.categories.Category; + +import generic.test.category.NightlyCategory; import ghidra.dbg.target.schema.SchemaContext; import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName; import ghidra.dbg.target.schema.XmlSchemaContext; import ghidra.trace.model.Trace; import ghidra.util.database.UndoableTransaction; +@Category(NightlyCategory.class) public class DebuggerThreadsProviderObjectTest extends DebuggerThreadsProviderTest { protected SchemaContext ctx; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeViewerProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeViewerProvider.java index a0bca264b6..2f0ad80960 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeViewerProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeViewerProvider.java @@ -4,9 +4,9 @@ * 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. diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/OpenFunctionTableAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/OpenFunctionTableAction.java index 3d8a3f4adb..afd9f3480f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/OpenFunctionTableAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/actions/OpenFunctionTableAction.java @@ -44,7 +44,7 @@ import util.CollectionUtils; /** * Opens a table chooser allowing the user to select functions from the current * program. The table displayed uses a {@link FunctionTableModel}. - * + * * @see FunctionComparisonService */ public class OpenFunctionTableAction extends DockingAction { @@ -64,7 +64,7 @@ public class OpenFunctionTableAction extends DockingAction { /** * Constructor - * + * * @param tool the plugin tool * @param provider the function comparison provider */ @@ -76,15 +76,14 @@ public class OpenFunctionTableAction extends DockingAction { this.comparisonService = tool.getService(FunctionComparisonService.class); setDescription("Add functions to comparison"); - setPopupMenuData(new MenuData(new String[] { "Add functions" }, - ADD_TO_COMPARISON_ICON, ADD_COMPARISON_GROUP)); + setPopupMenuData(new MenuData(new String[] { "Add functions" }, ADD_TO_COMPARISON_ICON, + ADD_COMPARISON_GROUP)); - ToolBarData newToolBarData = - new ToolBarData(ADD_TO_COMPARISON_ICON, ADD_COMPARISON_GROUP); + ToolBarData newToolBarData = new ToolBarData(ADD_TO_COMPARISON_ICON, ADD_COMPARISON_GROUP); setToolBarData(newToolBarData); - HelpLocation helpLocation = new HelpLocation(MultiFunctionComparisonPanel.HELP_TOPIC, - "Add_To_Comparison"); + HelpLocation helpLocation = + new HelpLocation(MultiFunctionComparisonPanel.HELP_TOPIC, "Add_To_Comparison"); setHelpLocation(helpLocation); KeyBindingData data = new KeyBindingData('A', InputEvent.SHIFT_DOWN_MASK); @@ -98,19 +97,14 @@ public class OpenFunctionTableAction extends DockingAction { @Override public void actionPerformed(ActionContext context) { - if (!(context.getComponentProvider() instanceof FunctionComparisonProvider)) { - return; - } - FunctionComparisonProvider provider = (FunctionComparisonProvider) context.getComponentProvider(); Program currentProgram = programManagerService.getCurrentProgram(); FunctionTableModel model = new FunctionTableModel(tool, currentProgram); model.reload(programManagerService.getCurrentProgram()); - TableSelectionDialog diag = - new TableSelectionDialog<>("Select Functions: " + currentProgram.getName(), - model, true); + TableSelectionDialog diag = new TableSelectionDialog<>( + "Select Functions: " + currentProgram.getName(), model, true); tool.showDialog(diag); List rows = diag.getSelectionItems(); if (CollectionUtils.isBlank(rows)) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/gotoquery/GoToHelper.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/gotoquery/GoToHelper.java index eafa0d4e37..875a416a3c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/gotoquery/GoToHelper.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/gotoquery/GoToHelper.java @@ -40,6 +40,7 @@ import ghidra.program.model.mem.Memory; import ghidra.program.model.symbol.*; import ghidra.program.util.*; import ghidra.util.HelpLocation; +import ghidra.util.Swing; import ghidra.util.table.AddressArrayTableModel; public class GoToHelper { @@ -80,6 +81,10 @@ public class GoToHelper { } public boolean goTo(final Navigatable navigatable, ProgramLocation loc, Program program) { + return Swing.runNow(() -> doGoTo(navigatable, loc, program)); + } + + private boolean doGoTo(final Navigatable navigatable, ProgramLocation loc, Program program) { if (loc == null || loc.getAddress() == null) { return false; } @@ -116,17 +121,6 @@ public class GoToHelper { return false; } -// If we want the goto to request focus then we will need to add a new parameter - you don't always -// want to request focus. -// // sometimes this gets call directly after creating a new provider window. Need to -// // request focus in an invokeLater to give WindowManager a chance to create the component -// // hierarchy tree. -// SwingUtilities.invokeLater(new Runnable() { -// public void run() { -// navigatable.requestFocus(); -// } -// }); - saveLocation(navigatable); return true; @@ -148,6 +142,7 @@ public class GoToHelper { if (loc != null) { return loc; } + if (gotoAddress.isStackAddress() || gotoAddress.isRegisterAddress()) { // Convert stack/register address into variable address Function func = program.getFunctionManager().getFunctionContaining(currentAddress); @@ -347,7 +342,7 @@ public class GoToHelper { String extProgName = externalLocation.getLibraryName(); if (Library.UNKNOWN.equals(extProgName)) { tool.setStatusInfo(" External location refers to " + Library.UNKNOWN + - " library. Unable to " + "perform navigation.", true); + " library. Unable to perform navigation.", true); return null; } @@ -391,6 +386,7 @@ public class GoToHelper { if (nameStack == null) { return null; // name is not valid for external program } + StringBuilder buf = new StringBuilder(); while (!nameStack.isEmpty()) { buf.append(nameStack.pop()); @@ -439,9 +435,9 @@ public class GoToHelper { if (result == OptionDialog.CANCEL_OPTION) { return; } - final DataTreeDialog dialog = new DataTreeDialog(null, - "Choose External Program (" + extProgName + ")", DataTreeDialog.OPEN); + DataTreeDialog dialog = new DataTreeDialog(null, + "Choose External Program (" + extProgName + ")", DataTreeDialog.OPEN); dialog.setSearchText(extProgName); dialog.setHelpLocation(new HelpLocation("ReferencesPlugin", "ChooseExternalProgram")); tool.showDialog(dialog); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/MultiProgramManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/MultiProgramManager.java index 096a2f129b..1cd8236b27 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/MultiProgramManager.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/MultiProgramManager.java @@ -17,7 +17,12 @@ package ghidra.app.plugin.core.progmgr; import java.net.URL; import java.rmi.NoSuchObjectException; -import java.util.*; +import java.util.Comparator; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; import org.jdom.Element; @@ -32,30 +37,36 @@ import ghidra.framework.plugintool.util.TransientToolState; import ghidra.framework.protocol.ghidra.GhidraURL; import ghidra.program.model.address.Address; import ghidra.program.model.listing.Program; -import ghidra.util.Msg; -import ghidra.util.SystemUtilities; +import ghidra.util.*; import ghidra.util.task.TaskLauncher; class MultiProgramManager implements DomainObjectListener, TransactionListener { - private static int nextProgramInfoInstance = 0; + // arbitrary counter for given ProgramInfo objects and ID to use for sorting + private static final AtomicInteger nextAvailableId = new AtomicInteger(); private ProgramManagerPlugin plugin; private PluginTool tool; - private ArrayList openProgramList; - private HashMap programMap; private ProgramInfo currentInfo; private TransactionMonitor txMonitor; private MyFolderListener folderListener; - private Runnable programChangedRunnable; + private Runnable programChangedRunnable; private boolean hasUnsavedPrograms; + // These data structures are accessed from multiple threads. Rather than synchronizing all + // accesses, we have chosen to be weakly consistent. We assume that any out-of-date checks + // for open program state will be self-correcting. For example, if a client checks to see if + // a program is open before opening it, then a repeated call to open the program will not + // result in a second copy of that program being opened. This is safe because program opens + // and closes are all done from the Swing thread. + private List openPrograms = new CopyOnWriteArrayList<>(); + private ConcurrentHashMap programMap = new ConcurrentHashMap<>(); + MultiProgramManager(ProgramManagerPlugin programManagerPlugin) { this.plugin = programManagerPlugin; this.tool = programManagerPlugin.getTool(); - openProgramList = new ArrayList<>(); - programMap = new HashMap<>(); + txMonitor = new TransactionMonitor(); txMonitor.setName("Transaction Open (Program being modified)"); tool.addStatusComponent(txMonitor, true, true); @@ -72,13 +83,13 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener { } void addProgram(Program p, URL ghidraURL, int state) { - ProgramInfo oldInfo = programMap.get(p); + ProgramInfo oldInfo = getInfo(p); if (oldInfo == null) { p.addConsumer(tool); ProgramInfo info = new ProgramInfo(p, state != ProgramManager.OPEN_HIDDEN); info.ghidraURL = ghidraURL; - openProgramList.add(info); - Collections.sort(openProgramList); + openPrograms.add(info); + openPrograms.sort(Comparator.naturalOrder()); programMap.put(p, info); fireOpenEvents(p); @@ -100,16 +111,15 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener { void dispose() { tool.getProject().getProjectData().removeDomainFolderChangeListener(folderListener); fireActivatedEvent(null); - Iterator it = programMap.keySet().iterator(); - while (it.hasNext()) { - Program p = it.next(); + + for (Program p : programMap.keySet()) { p.removeListener(this); p.removeTransactionListener(this); fireCloseEvents(p); p.release(tool); } programMap.clear(); - openProgramList.clear(); + openPrograms.clear(); tool.setSubTitle(""); tool.removeStatusComponent(txMonitor); tool = null; @@ -117,38 +127,38 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener { } void removeProgram(Program p) { - ProgramInfo info = programMap.get(p); - if (info != null) { - if (info.owner != null) { - // persist program - info.setVisible(false); - if (info == currentInfo) { - ProgramInfo newCurrent = findNextCurrent(); - setCurrentProgram(newCurrent); - } + ProgramInfo info = getInfo(p); + if (info == null) { + return; + } + + if (info.owner != null) { + // persist program + info.setVisible(false); + if (info == currentInfo) { + ProgramInfo newCurrent = findNextCurrent(); + setCurrentProgram(newCurrent); } - else { - p.removeTransactionListener(this); - programMap.remove(p); - p.removeListener(this); - openProgramList.remove(info); - if (info == currentInfo) { - ProgramInfo newCurrent = findNextCurrent(); - setCurrentProgram(newCurrent); - } - fireCloseEvents(p); - p.release(tool); - if (openProgramList.isEmpty()) { - plugin.getTool().clearLastEvents(); - } + } + else { + p.removeTransactionListener(this); + programMap.remove(p); + p.removeListener(this); + openPrograms.remove(info); + if (info == currentInfo) { + ProgramInfo newCurrent = findNextCurrent(); + setCurrentProgram(newCurrent); + } + fireCloseEvents(p); + p.release(tool); + if (openPrograms.isEmpty()) { + plugin.getTool().clearLastEvents(); } } } private ProgramInfo findNextCurrent() { - Iterator iter = openProgramList.iterator(); - while (iter.hasNext()) { - ProgramInfo pi = iter.next(); + for (ProgramInfo pi : openPrograms) { if (pi.visible) { return pi; } @@ -158,23 +168,17 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener { Program[] getOtherPrograms() { Program currentProgram = getCurrentProgram(); - ArrayList list = new ArrayList<>(); - int size = openProgramList.size(); - for (int index = 0; index < size; index++) { - Program program = openProgramList.get(index).program; - if (currentProgram != program) { - list.add(program); - } - } + List list = openPrograms.stream() + .map(info -> info.program) + .filter(program -> program != currentProgram) + .collect(Collectors.toList()); return list.toArray(new Program[list.size()]); } Program[] getAllPrograms() { - Program[] programs = new Program[openProgramList.size()]; - for (int i = 0; i < programs.length; i++) { - programs[i] = (openProgramList.get(i)).program; - } - return programs; + List list = + openPrograms.stream().map(info -> info.program).collect(Collectors.toList()); + return list.toArray(Program[]::new); } Program getCurrentProgram() { @@ -191,16 +195,18 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener { } } - ProgramInfo info = programMap.get(p); + if (p == null) { + return; + } + + ProgramInfo info = getInfo(p); if (info != null) { setCurrentProgram(info); } } Program getProgram(Address addr) { - Iterator it = openProgramList.iterator(); - while (it.hasNext()) { - ProgramInfo pi = it.next(); + for (ProgramInfo pi : openPrograms) { if (pi.program.getMemory().contains(addr)) { return pi.program; } @@ -257,26 +263,17 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener { } } - /** - * @param program - */ private void fireOpenEvents(Program program) { plugin.firePluginEvent(new ProgramOpenedPluginEvent("", program)); plugin.firePluginEvent(new OpenProgramPluginEvent("", program)); } - /** - * @param program - */ private void fireCloseEvents(Program program) { plugin.firePluginEvent(new ProgramClosedPluginEvent("", program)); plugin.firePluginEvent(new CloseProgramPluginEvent("", program, true)); // tool.contextChanged(); } - /** - * @param p - */ private void fireActivatedEvent(Program newProgram) { plugin.firePluginEvent(new ProgramActivatedPluginEvent("", newProgram)); } @@ -285,14 +282,12 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener { plugin.firePluginEvent(new ProgramVisibilityChangePluginEvent("", program, isVisible)); } - /** - * @see ghidra.framework.model.DomainObjectListener#domainObjectChanged(ghidra.framework.model.DomainObjectChangedEvent) - */ @Override public void domainObjectChanged(DomainObjectChangedEvent ev) { if (!(ev.getSource() instanceof Program)) { return; } + Program program = (Program) ev.getSource(); if (ev.containsEvent(DomainObject.DO_DOMAIN_FILE_CHANGED) || ev.containsEvent(DomainObject.DO_OBJECT_ERROR)) { @@ -320,7 +315,6 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener { "\nby the local filesystem or server."; } - //abort(); Msg.showError(this, tool.getToolFrame(), "Severe Error Condition", msg); removeProgram(program); return; @@ -330,64 +324,24 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener { } } - /** - * @return - */ public boolean isEmpty() { - return openProgramList.isEmpty(); + return openPrograms.isEmpty(); } - /** - * @param program - * @return - */ - public boolean contains(Program program) { - return programMap.containsKey(program); - } - - private class MyFolderListener extends DomainFolderListenerAdapter { - - @Override - public void domainFileObjectReplaced(DomainFile file, DomainObject oldObject) { - - /** - * Special handling for when a file is checked-in. The existing program has be moved - * to a proxy file (no longer in the project) so that it can be closed and the program - * re-opened with the new version after the check-in merge. - */ - - if (!programMap.containsKey(oldObject)) { - return; - } - Element dataState = null; - if (currentInfo != null && currentInfo.program == oldObject) { - // save dataState as though the project state was saved and re-opened to simulate - // recovering after closing the program during this swap - dataState = tool.saveDataStateToXml(true); - } - OpenProgramTask openTask = new OpenProgramTask(file, -1, this); - openTask.setSilent(); -// OpenDomainFileTask openTask = new OpenDomainFileTask(file, -1, tool, -// plugin, true, dataState != null ? ProgramManager.OPEN_CURRENT : ProgramManager.OPEN_VISIBLE); - new TaskLauncher(openTask, tool.getToolFrame()); - Program openProgram = openTask.getOpenProgram(); - plugin.openProgram(openProgram, - dataState != null ? ProgramManager.OPEN_CURRENT : ProgramManager.OPEN_VISIBLE); - openProgram.release(this); - removeProgram((Program) oldObject); - if (dataState != null) { - tool.restoreDataStateFromXml(dataState); - } + public boolean contains(Program p) { + if (p == null) { + return false; } + return programMap.containsKey(p); } - boolean isVisible(Program program) { - ProgramInfo info = programMap.get(program); + boolean isVisible(Program p) { + ProgramInfo info = getInfo(p); return info != null ? info.visible : false; } void releaseProgram(Program program, Object owner) { - ProgramInfo info = programMap.get(program); + ProgramInfo info = getInfo(program); if (info != null && info.owner == owner) { info.owner = null; if (!info.visible) { @@ -403,7 +357,7 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener { } boolean setPersistentOwner(Program program, Object owner) { - ProgramInfo info = programMap.get(program); + ProgramInfo info = getInfo(program); if (info != null && info.owner == null) { info.owner = owner; return true; @@ -411,37 +365,81 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener { return false; } - public boolean isPersistent(Program program) { - ProgramInfo info = programMap.get(program); + boolean isPersistent(Program p) { + ProgramInfo info = getInfo(p); return (info != null && info.owner != null); } - private class ProgramInfo implements Comparable { + private ProgramInfo getInfo(Program p) { + if (p == null) { + return null; + } + return programMap.get(p); + } - Program program; - URL ghidraURL; - TransientToolState lastState; - private int instance; - boolean visible; - Object owner; - - ProgramInfo(Program p, boolean visible) { - this.program = p; - this.visible = visible; - synchronized (ProgramInfo.class) { - instance = ++nextProgramInfoInstance; + Program getOpenProgram(URL ghidraURL) { + if (!GhidraURL.isServerRepositoryURL(ghidraURL)) { + return null; + } + URL normalizedURL = GhidraURL.getNormalizedURL(ghidraURL); + for (ProgramInfo info : programMap.values()) { + URL url = info.ghidraURL; + if (url != null && url.equals(normalizedURL)) { + return info.program; } } + return null; + } - public void setVisible(boolean state) { - visible = state; - fireVisibilityChangeEvent(program, visible); + Program getOpenProgram(DomainFile domainFile, int version) { + for (Program program : programMap.keySet()) { + DomainFile programDomainFile = program.getDomainFile(); + if (filesMatch(domainFile, version, programDomainFile)) { + return program; + } + } + return null; + } + + private boolean filesMatch(DomainFile file1, int version, DomainFile file2) { + if (!file1.getPathname().equals(file2.getPathname())) { + return false; } - @Override - public int compareTo(ProgramInfo info) { - return instance - info.instance; + if (file1.isCheckedOut() != file2.isCheckedOut()) { + return false; } + + if (!SystemUtilities.isEqual(file1.getProjectLocator(), file2.getProjectLocator())) { + return false; + } + + int openVersion = file2.isReadOnly() ? file2.getVersion() : -1; + return version == openVersion; + } + + /** + * Returns true if there is at least one program that has unsaved changes. + * @return true if there is at least one program that has unsaved changes. + */ + boolean hasUnsavedPrograms() { + return hasUnsavedPrograms; + } + + private boolean checkForUnsavedPrograms() { + // first check the current program as that is the one most likely to have changes + Program currentProgram = getCurrentProgram(); + if (currentProgram != null && currentProgram.isChanged()) { + return true; + } + // look at all the open programs to see if any have changes + for (ProgramInfo programInfo : openPrograms) { + if (programInfo.program.isChanged()) { + return true; + } + } + return false; + } @Override @@ -461,80 +459,69 @@ class MultiProgramManager implements DomainObjectListener, TransactionListener { @Override public void undoStackChanged(DomainObjectAdapterDB domainObj) { - SystemUtilities.runSwingLater(programChangedRunnable); + Swing.runLater(programChangedRunnable); } - public Program getOpenProgram(URL ghidraURL) { - if (!GhidraURL.isServerRepositoryURL(ghidraURL)) { - return null; - } - URL normalizedURL = GhidraURL.getNormalizedURL(ghidraURL); - for (ProgramInfo info : programMap.values()) { - URL url = info.ghidraURL; - if (url != null && url.equals(normalizedURL)) { - return info.program; +//================================================================================================== +// Inner Classes +//================================================================================================== + private class MyFolderListener extends DomainFolderListenerAdapter { + + @Override + public void domainFileObjectReplaced(DomainFile file, DomainObject oldObject) { + + /** + * Special handling for when a file is checked-in. The existing program has be moved + * to a proxy file (no longer in the project) so that it can be closed and the program + * re-opened with the new version after the check-in merge. + */ + + if (!programMap.containsKey(oldObject)) { + return; + } + Element dataState = null; + if (currentInfo != null && currentInfo.program == oldObject) { + // save dataState as though the project state was saved and re-opened to simulate + // recovering after closing the program during this swap + dataState = tool.saveDataStateToXml(true); + } + OpenProgramTask openTask = new OpenProgramTask(file, -1, this); + openTask.setSilent(); + new TaskLauncher(openTask, tool.getToolFrame()); + Program openProgram = openTask.getOpenProgram(); + plugin.openProgram(openProgram, + dataState != null ? ProgramManager.OPEN_CURRENT : ProgramManager.OPEN_VISIBLE); + openProgram.release(this); + removeProgram((Program) oldObject); + if (dataState != null) { + tool.restoreDataStateFromXml(dataState); } } - return null; } - public Program getOpenProgram(DomainFile domainFile, int version) { - for (Program program : programMap.keySet()) { - DomainFile programDomainFile = program.getDomainFile(); - if (filesMatch(domainFile, version, programDomainFile)) { - return program; - } - } - return null; - } + private class ProgramInfo implements Comparable { - private boolean filesMatch(DomainFile file, int version, DomainFile openFile) { - if (!file.getPathname().equals(openFile.getPathname())) { - return false; + private Program program; + private URL ghidraURL; + private TransientToolState lastState; + private int instance; + private boolean visible; + private Object owner; + + ProgramInfo(Program p, boolean visible) { + this.program = p; + this.visible = visible; + instance = nextAvailableId.incrementAndGet(); } - if (file.isCheckedOut() != openFile.isCheckedOut()) { - return false; + public void setVisible(boolean state) { + visible = state; + fireVisibilityChangeEvent(program, visible); } - if (!SystemUtilities.isEqual(file.getProjectLocator(), openFile.getProjectLocator())) { - return false; + @Override + public int compareTo(ProgramInfo info) { + return instance - info.instance; } - - int openVersion = openFile.isReadOnly() ? openFile.getVersion() : -1; - return version == openVersion; - } - - /** - * Returns true if this ProgramManager is managing the given program - * @param program the program to check - * @return true if this ProgramManager is managing the given programs - */ - public boolean hasProgram(Program program) { - return programMap.containsKey(program); - } - - /** - * Returns true if there is at least one program that has unsaved changes. - * @return true if there is at least one program that has unsaved changes. - */ - public boolean hasUnsavedPrograms() { - return hasUnsavedPrograms; - } - - private boolean checkForUnsavedPrograms() { - // first check the current program as that is the one most likely to have changes - Program currentProgram = getCurrentProgram(); - if (currentProgram != null && currentProgram.isChanged()) { - return true; - } - // look at all the open programs to see if any have changes - for (ProgramInfo programInfo : openProgramList) { - if (programInfo.program.isChanged()) { - return true; - } - } - return false; - } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java index 53a4e79bf3..6fc4d4aac8 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java @@ -23,7 +23,6 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.atomic.AtomicReference; import docking.action.DockingAction; import docking.action.builder.ActionBuilder; @@ -138,17 +137,14 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager { } @Override - public Program openProgram(final URL ghidraURL, final int state) { + public Program openProgram(URL ghidraURL, int state) { if (locked) { Msg.showError(this, tool.getToolFrame(), "Open Program Failed", "Program manager is locked and cannot open additional programs"); return null; } - AtomicReference ref = new AtomicReference<>(); - Runnable r = () -> ref.set(doOpenProgram(ghidraURL, state)); - SystemUtilities.runSwingNow(r); - return ref.get(); + return Swing.runNow(() -> doOpenProgram(ghidraURL, state)); } private void messageBadProgramURL(URL ghidraURL) { @@ -341,7 +337,7 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager { public boolean closeOtherPrograms(boolean ignoreChanges) { Program[] otherPrograms = programMgr.getOtherPrograms(); Runnable r = () -> doCloseAllPrograms(otherPrograms, ignoreChanges); - SystemUtilities.runSwingNow(r); + Swing.runNow(r); return programMgr.isEmpty(); } @@ -349,7 +345,7 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager { public boolean closeAllPrograms(boolean ignoreChanges) { Program[] openPrograms = programMgr.getAllPrograms(); Runnable r = () -> doCloseAllPrograms(openPrograms, ignoreChanges); - SystemUtilities.runSwingNow(r); + Swing.runNow(r); return programMgr.isEmpty(); } @@ -397,7 +393,7 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager { } Runnable r = () -> { // Note: The tool.canCloseDomainObject() call must come before the - // programSaveMgr.canClose()call since plugins may save changes to the program + // programSaveMgr.canClose() call since plugins may save changes to the program // so that they can close. if (ignoreChanges || program.isClosed() || programMgr.isPersistent(program) || (tool.canCloseDomainObject(program) && programSaveMgr.canClose(program))) { @@ -405,7 +401,7 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager { contextChanged(); } }; - SystemUtilities.runSwingNow(r); + Swing.runNow(r); return !programMgr.contains(program); } @@ -436,7 +432,7 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager { programMgr.setCurrentProgram(p); contextChanged(); }; - SystemUtilities.runSwingNow(r); + Swing.runNow(r); } @Override @@ -476,7 +472,7 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager { } contextChanged(); }; - SystemUtilities.runSwingNow(r); + Swing.runNow(r); } @Override @@ -506,13 +502,13 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager { int subMenuGroup = 1; - DockingAction openAction = new ActionBuilder("Open File", getName()) - .menuPath(ToolConstants.MENU_FILE, "&Open...") - .menuGroup(OPEN_GROUP, Integer.toString(subMenuGroup++)) - .keyBinding("ctrl O") - .enabledWhen(c -> !locked) - .onAction(c -> open()) - .buildAndInstall(tool); + DockingAction openAction = + new ActionBuilder("Open File", getName()).menuPath(ToolConstants.MENU_FILE, "&Open...") + .menuGroup(OPEN_GROUP, Integer.toString(subMenuGroup++)) + .keyBinding("ctrl O") + .enabledWhen(c -> !locked) + .onAction(c -> open()) + .buildAndInstall(tool); openAction.addToWindowWhen(ProgramActionContext.class); tool.addAction(new CloseProgramAction(this, OPEN_GROUP, subMenuGroup++)); @@ -522,7 +518,7 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager { .enabled(false) .withContext(ProgramActionContext.class) .inWindow(ActionBuilder.When.CONTEXT_MATCHES) - .enabledWhen(c -> programMgr.hasProgram(c.getProgram())) + .enabledWhen(c -> programMgr.contains(c.getProgram())) .onAction(c -> closeOtherPrograms(false)) .buildAndInstall(tool); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/services/GoToService.java b/Ghidra/Features/Base/src/main/java/ghidra/app/services/GoToService.java index eb96abeeb5..2c775e3d66 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/services/GoToService.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/services/GoToService.java @@ -22,12 +22,20 @@ import ghidra.program.model.address.Address; import ghidra.program.model.listing.Program; import ghidra.program.model.symbol.ExternalLocation; import ghidra.program.util.ProgramLocation; +import ghidra.util.Swing; import ghidra.util.task.TaskMonitor; /** * The GoToService provides a general service for plugins to generate GoTo * events. The provider of this service will take care of interfacing with * any history service that may be available. + *

+ * This class will execute all {@code goTo} calls on the Java Swing thread. This will happen in + * a blocking manner if the client calls from any other thread. This has the potential to lead + * to deadlocks if the client is using custom synchronization. Care must be taken to not be + * holding any lock that will cause the Swing thread to block when using this class from any other + * thread. To work around this issue, clients can always call this service from within a + * {@link Swing#runLater(Runnable)} call, which will prevent any deadlock issues. */ @ServiceInfo(defaultProvider = GoToServicePlugin.class, description = "Navigate to a program location") public interface GoToService { @@ -41,7 +49,7 @@ public interface GoToService { /** * Generates a GoTo event and handles any history state that needs to be saved. This method * will attempt to find the program that contains the given ProgramLocation. - * + * * @param loc location to go to * @return true if the go to was successful * @see #goTo(ProgramLocation, Program) @@ -49,13 +57,13 @@ public interface GoToService { public boolean goTo(ProgramLocation loc); /** - * Generates a GoTo event and handles any history state that needs to be saved. This - * overloaded version of {@link #goTo(Address)} uses the given program as the program - * within which to perform the GoTo. If the given program does not contain the given - * address, then the GoTo will not be performed and false will be returned. Passing - * null as the program parameter will cause this method to attempt to find - * a program that contains the given ProgramLocation. - * + * Generates a GoTo event and handles any history state that needs to be saved. This + * overloaded version of {@link #goTo(Address)} uses the given program as the program within + * which to perform the GoTo. If the given program does not contain the given address, then + * the GoTo will not be performed and false will be returned. Passing null as the + * program parameter will cause this method to attempt to find a program that + * contains the given ProgramLocation. + * * @param loc location to go to * @param program the program within which to perform the GoTo * @return true if the go to was successful @@ -63,20 +71,46 @@ public interface GoToService { */ public boolean goTo(ProgramLocation loc, Program program); + /** + * Generates a GoTo event to the given location in the given program. + * + * @param navigatable the destination navigatable + * @param loc the location + * @param program program + * @return true if the go to was successful + */ public boolean goTo(Navigatable navigatable, ProgramLocation loc, Program program); + /** + * Generates a GoTo event to the given address. The refAddress is used to determine if + * there is a specific symbol reference from that reference. + * + * @param navigatable the destination navigatable + * @param program program + * @param address the destination address + * @param refAddress the from reference address + * @return true if the go to was successful + */ public boolean goTo(Navigatable navigatable, Program program, Address address, Address refAddress); /** - * Generates a GoTo event to the goToAddress or symbol. The currentAddress is used to - * determine if there is a specific symbol reference from the current address. - * @param currentAddress the current address + * Generates a GoTo event to the given address. The fromAddress is used to determine if + * there is a specific symbol reference from the current address. + * + * @param fromAddress the current address + * @param address the address to goto + * @return true if the go to was successful + */ + public boolean goTo(Address fromAddress, Address address); + + /** + * Generates a GoTo event to the given address for the specific navigatable. + * + * @param navigatable the destination navigatable * @param goToAddress the address to goto * @return true if the go to was successful */ - public boolean goTo(Address currentAddress, Address goToAddress); - public boolean goTo(Navigatable navigatable, Address goToAddress); /** @@ -89,12 +123,12 @@ public interface GoToService { /** * Generates a GoTo event to the gotoAddress. This overloaded version of - * {@link #goTo(Address)} uses the given program as the program within which to - * perform the GoTo. If the given program does not contain the given address, then the - * GoTo will not be performed and false will be returned. Passing null as the - * program parameter will cause this method to attempt to find - * a program that contains the given ProgramLocation. - * + * {@link #goTo(Address)} uses the given program as the program within which to perform the + * GoTo. If the given program does not contain the given address, then the GoTo will not be + * performed and false will be returned. Passing null as the program + * parameter will cause this method to attempt to find a program that contains the given + * ProgramLocation. + * * @param goToAddress the address to goto * @param program the program within which to perform the GoTo * @return true if the go to was successful @@ -103,67 +137,82 @@ public interface GoToService { public boolean goTo(Address goToAddress, Program program); /** - * Navigate to either the external program location or address linkage location. - * Specific behavior may vary based upon implementation. - + * Navigate to either the external program location or address linkage location. Specific + * behavior may vary based upon implementation. + * * @param externalLoc external location - * @param checkNavigationOption if true the service navigation - * option will be used to determine if navigation to the external program will be - * attempted, or if navigation to the external linkage location within the current - * program will be attempted. If false, the implementations default behavior - * will be performed. - * @return true if either navigation to the external program or to a - * linkage location was completed successfully. + * @param checkNavigationOption if true the service navigation option will be used to determine + * if navigation to the external program will be attempted, or if navigation to the + * external linkage location within the current program will be attempted. If false, the + * implementations default behavior will be performed. + * @return true if either navigation to the external program or to a linkage location was + * completed successfully. */ public boolean goToExternalLocation(ExternalLocation externalLoc, boolean checkNavigationOption); /** - * Navigate to either the external program location or address linkage location. - * Specific behavior may vary based upon implementation. - * + * Navigate to either the external program location or address linkage location. Specific + * behavior may vary based upon implementation. + * * @param navigatable Navigatable * @param externalLoc external location - * @param checkNavigationOption if true the service navigation - * option will be used to determine if navigation to the external program will be - * attempted, or if navigation to the external linkage location within the current - * program will be attempted. If false, the implementations default behavior - * will be performed. - * @return true if either navigation to the external program or to a - * linkage location was completed successfully. + * @param checkNavigationOption if true the service navigation option will be used to determine + * if navigation to the external program will be attempted, or if navigation to the + * external linkage location within the current program will be attempted. If false, the + * implementations default behavior will be performed. + * @return true if either navigation to the external program or to a linkage location was + * completed successfully. */ public boolean goToExternalLocation(Navigatable navigatable, ExternalLocation externalLoc, boolean checkNavigationOption); /** - * Parses the input string as either: - * an address/symbol expression (0x1000+5, or LAB1000+5) - * a symbol wildcard expression (LAB*, LAB?100) - * a symbol lookup - * an address lookup - * + * Generates a GoTo event for the given query. + *

* If the query results in more than one location, a list of locations will be displayed. - * If the query results in only one location, then a goto event will be fired(except for a + * If the query results in only one location, then a goto event will be fired(except for a * wildcard query in which case a list will still be displayed. - * + *

* The listener will be notified after query and will indicate the query status. - * + * * @param fromAddr The address used to determine the scope of the query * @param queryData the query input data - * @param listener the listener that will be notified when the query completes. + * @param listener the listener that will be notified when the query completes * @param monitor the task monitor - * @return true if the queryInput is found or appears to be a wildcard search. + * @return true if the queryInput is found or appears to be a wildcard search */ public boolean goToQuery(Address fromAddr, QueryData queryData, GoToServiceListener listener, TaskMonitor monitor); + /** + * Generates a GoTo event for the given query. + *

+ * If the query results in more than one location, a list of locations will be displayed. + * If the query results in only one location, then a goto event will be fired(except for a + * wildcard query in which case a list will still be displayed. + *

+ * The listener will be notified after query and will indicate the query status. + * + * @param navigatable the destination for the go to event + * @param fromAddr The address used to determine the scope of the query + * @param queryData the query input data + * @param listener the listener that will be notified when the query completes + * @param monitor the task monitor + * @return true if the queryInput is found or appears to be a wildcard search + */ public boolean goToQuery(Navigatable navigatable, Address fromAddr, QueryData queryData, GoToServiceListener listener, TaskMonitor monitor); - public GoToOverrideService getOverrideService(); - - public void setOverrideService(GoToOverrideService override); - + /** + * Returns the default navigatable that is the destination for GoTo events. + * @return the navigatable + */ public Navigatable getDefaultNavigatable(); + @Deprecated(forRemoval = true, since = "10.2") + public GoToOverrideService getOverrideService(); + + @Deprecated(forRemoval = true, since = "10.2") + public void setOverrideService(GoToOverrideService override); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/services/ProgramManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/services/ProgramManager.java index 1191106483..a7e700a22c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/services/ProgramManager.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/services/ProgramManager.java @@ -29,9 +29,7 @@ import ghidra.program.model.listing.Program; * Service for managing programs. Multiple programs may be open in a tool, but only one is active at * any given time. */ -@ServiceInfo( - defaultProvider = ProgramManagerPlugin.class, - description = "Get the currently open program") +@ServiceInfo(defaultProvider = ProgramManagerPlugin.class, description = "Get the currently open program") public interface ProgramManager { /** @@ -53,14 +51,14 @@ public interface ProgramManager { /** * Return the program that is currently active. - * + * * @return may return null if no program is open */ public Program getCurrentProgram(); /** * Returns true if the specified program is open and considered visible to the user. - * + * * @param program the program * @return true if the specified program is open and considered visible to the user */ @@ -68,7 +66,7 @@ public interface ProgramManager { /** * Closes the currently active program - * + * * @return true if the close is successful. false if the close fails or if there is no program * currently active. */ @@ -76,7 +74,7 @@ public interface ProgramManager { /** * Open the program corresponding to the given url. - * + * * @param ghidraURL valid server-based program URL * @param state initial open state (OPEN_HIDDEN, OPEN_CURRENT, OPEN_VISIBLE). The visibility * states will be ignored if the program is already open. @@ -88,7 +86,7 @@ public interface ProgramManager { /** * Open the program for the given domainFile. Once open it will become the active program. - * + * * @param domainFile domain file that has the program * @return null if the user canceled the "open" for the new program */ @@ -96,10 +94,10 @@ public interface ProgramManager { /** * Open the program for the given domainFile. Once open it will become the active program. - * + * *

* Note: this method functions exactly as {@link #openProgram(DomainFile)} - * + * * @param domainFile domain file that has the program * @param dialogParent unused * @return the program @@ -112,7 +110,7 @@ public interface ProgramManager { /** * Opens the specified version of the program represented by the given DomainFile. This method * should be used for shared DomainFiles. The newly opened file will be made the active program. - * + * * @param df the DomainFile to open * @param version the version of the Program to open * @return the opened program or null if the given version does not exist. @@ -121,7 +119,7 @@ public interface ProgramManager { /** * Open the program for the given domainFile - * + * * @param domainFile domain file that has the program * @param version the version of the Program to open. Specify DomainFile.DEFAULT_VERSION for * file update mode. @@ -135,7 +133,7 @@ public interface ProgramManager { /** * Opens the program to the tool. In this case the program is already open, but this tool may * not have it registered as open. The program is made the active program. - * + * * @param program the program to register as open with the tool. */ public void openProgram(Program program); @@ -143,7 +141,7 @@ public interface ProgramManager { /** * Opens the program to the tool. In this case the program is already open, but this tool may * not have it registered as open. The program is made the active program. - * + * * @param program the program to register as open with the tool. * @param current if true, the program is made the current active program. If false, then the * program is made active only if it the first open program in the tool. @@ -154,7 +152,7 @@ public interface ProgramManager { /** * Open the specified program in the tool. - * + * * @param program the program * @param state initial open state (OPEN_HIDDEN, OPEN_CURRENT, OPEN_VISIBLE). The visibility * states will be ignored if the program is already open. @@ -168,7 +166,7 @@ public interface ProgramManager { /** * Saves the specified program, possibly prompting the user for a new name. - * + * * @param program the program */ public void saveProgram(Program program); @@ -180,7 +178,7 @@ public interface ProgramManager { /** * Prompts the user to save the specified program to a selected file. - * + * * @param program the program */ public void saveProgramAs(Program program); @@ -188,13 +186,15 @@ public interface ProgramManager { /** * Establish a persistent owner on an open program. This will cause the program manager to imply * make a program hidden if it is closed. - * + * * @param program the program * @param owner the owner * @return true if program is open and another object is not already the owner, or the specified * owner is already the owner. * @see #releaseProgram(Program, Object) + * @deprecated this method is no longer used by the system */ + @Deprecated(forRemoval = true, since = "10.2") public boolean setPersistentOwner(Program program, Object owner); /** @@ -205,10 +205,12 @@ public interface ProgramManager { * to save or keep the program open. *

* If persistentOwner is not the correct owner, the method will have no affect. - * + * * @param program the program * @param persistentOwner the owner defined by {@link #setPersistentOwner(Program, Object)} + * @deprecated this method is no longer used by the system */ + @Deprecated(forRemoval = true, since = "10.2") public void releaseProgram(Program program, Object persistentOwner); /** @@ -217,7 +219,7 @@ public interface ProgramManager { * then the program is closed for this tool only and the user is not prompted to save the * program regardless of the ignoreChanges flag. Otherwise, if ignoreChanges is false and * changes have been made, the user is prompted to save the program. - * + * * @param program the program to close. * @param ignoreChanges if true, the program is closed without saving any changes. * @return true if the program was closed. Returns false if the user canceled the close while @@ -230,7 +232,7 @@ public interface ProgramManager { * Closes all open programs in this tool except the current program. If this tool is the only * tool with a program open and that program has changes, then the user will be prompted to * close each such file. (Providing the ignoreChanges flag is false) - * + * * @param ignoreChanges if true, the programs will be closed without saving changes. * @return true if all other programs were closed. Returns false if the user canceled the close * while being prompted to save. @@ -241,7 +243,7 @@ public interface ProgramManager { * Closes all open programs in this tool. If this tool is the only tool with a program open and * that program has changes, then the user will be prompted to close each such file. (Providing * the ignoreChanges flag is false) - * + * * @param ignoreChanges if true, the programs will be closed without saving changes. * @return true if all programs were closed. Returns false if the user canceled the close while * being prompted to save. @@ -250,7 +252,7 @@ public interface ProgramManager { /** * Sets the given program to be the current active program in the tool. - * + * * @param p the program to make active. */ public void setCurrentProgram(Program p); @@ -260,7 +262,7 @@ public interface ProgramManager { * Programs are searched in the order they were opened within a given priority. Program are * initially opened with the PRIORITY_NORMAL priority, but can be set to have PRIORITY_HIGH or * PRIORITY_LOW. - * + * * @param addr the address for which to search. * @return the first program that can be found to contain the given address. */ @@ -268,7 +270,7 @@ public interface ProgramManager { /** * Returns a list of all open program. - * + * * @return the programs */ public Program[] getAllOpenPrograms(); @@ -276,7 +278,7 @@ public interface ProgramManager { /** * Allows program manager state to be locked/unlocked. While locked, the program manager will * not support opening additional programs. - * + * * @param state locked if true, unlocked if false * @deprecated deprecated for 10.1; removal for 10.3 or later */ @@ -285,7 +287,7 @@ public interface ProgramManager { /** * Returns true if program manager is in the locked state - * + * * @return true if program manager is in the locked state * @deprecated deprecated for 10.1; removal for 10.3 or later */ diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/navigation/GoToQuery.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/navigation/GoToQuery.java index 637fbce3bf..74ecf9a085 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/navigation/GoToQuery.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/navigation/GoToQuery.java @@ -42,7 +42,7 @@ import ghidra.program.model.symbol.*; import ghidra.program.util.AddressEvaluator; import ghidra.program.util.ProgramLocation; import ghidra.util.Msg; -import ghidra.util.SystemUtilities; +import ghidra.util.Swing; import ghidra.util.table.AddressArrayTableModel; import ghidra.util.table.GhidraProgramTableModel; import ghidra.util.task.TaskMonitor; @@ -187,7 +187,7 @@ public class GoToQuery { return; } - SystemUtilities.runIfSwingOrPostSwingLater(() -> { + Swing.runIfSwingOrRunLater(() -> { model = new AddressArrayTableModel("Goto: ", plugin.getTool(), program, validAddresses, monitor); model.addInitialLoadListener(tableModelListener); @@ -203,7 +203,7 @@ public class GoToQuery { return; } - SystemUtilities.runIfSwingOrPostSwingLater(() -> { + Swing.runIfSwingOrRunLater(() -> { model = new GoToQueryResultsTableModel(program, plugin.getTool(), locations, monitor); model.addInitialLoadListener(tableModelListener); }); @@ -214,7 +214,7 @@ public class GoToQuery { return false; } - SystemUtilities.runIfSwingOrPostSwingLater(() -> { + Swing.runIfSwingOrRunLater(() -> { model = new GoToQueryResultsTableModel(navigatable.getProgram(), queryData, plugin.getTool(), maxHits, monitor); model.addInitialLoadListener(tableModelListener); @@ -337,7 +337,7 @@ public class GoToQuery { return false; } - SystemUtilities.runIfSwingOrPostSwingLater(() -> { + Swing.runIfSwingOrRunLater(() -> { Program program = navigatable.getProgram(); model = new GoToQueryResultsTableModel(program, cleanupQuery(program, queryData), plugin.getTool(), maxHits, monitor); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ListingPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ListingPanel.java index 0602307088..41929a225f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ListingPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ListingPanel.java @@ -46,6 +46,7 @@ import ghidra.program.model.listing.*; import ghidra.program.model.symbol.*; import ghidra.program.util.*; import ghidra.util.Msg; +import ghidra.util.Swing; import ghidra.util.layout.HorizontalLayout; public class ListingPanel extends JPanel implements FieldMouseListener, FieldLocationListener, @@ -95,7 +96,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Constructs a new ListingPanel using the given FormatManager and ServiceProvider. - * + * * @param manager the FormatManager to use. */ public ListingPanel(FormatManager manager) { @@ -125,7 +126,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Constructs a new ListingPanel for the given program. - * + * * @param mgr the FormatManager to use. * @param program the program for which to create a new ListingPanel */ @@ -136,7 +137,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Constructs a new ListingPanel with the given FormatManager and ListingLayoutModel - * + * * @param mgr the FormatManager to use * @param model the ListingLayoutModel to use. */ @@ -182,7 +183,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Sets the ProgramLocationListener. Only one listener is supported - * + * * @param listener the ProgramLocationListener to use. */ public void setProgramLocationListener(ProgramLocationListener listener) { @@ -191,7 +192,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Sets the ProgramSelectionListener. Only one listener is supported - * + * * @param listener the ProgramSelectionListener to use. */ public void setProgramSelectionListener(ProgramSelectionListener listener) { @@ -204,7 +205,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Sets the ListingLayoutModel to use. - * + * * @param newModel the model to use. */ public void setListingModel(ListingModel newModel) { @@ -224,7 +225,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Sets whether or not the field header component is visible at the top of the listing panel - * + * * @param show if true, the header component will be show, otherwise it will be hidden. */ public void showHeader(boolean show) { @@ -283,7 +284,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Adds the MarginProvider to this panel - * + * * @param provider the MarginProvider that will provide components to display in this panel's * left margin area. */ @@ -375,7 +376,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Add a change listener to be notified whenever the indexMap changes. - * + * * @param listener the listener to be added. */ public void addIndexMapChangeListener(ChangeListener listener) { @@ -384,7 +385,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Removes the change listener to be notified when the indexMap changes. - * + * * @param listener the listener to be removed. */ public void removeIndexMapChangeListener(ChangeListener listener) { @@ -393,7 +394,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Removes the given margin provider from this panel - * + * * @param provider the MarginProvider to remove. */ public void removeMarginProvider(MarginProvider provider) { @@ -403,7 +404,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Adds the given OverviewProvider with will be displayed in this panels right margin area. - * + * * @param provider the OverviewProvider to display. */ public void addOverviewProvider(OverviewProvider provider) { @@ -414,7 +415,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Removes the given OverviewProvider from this panel - * + * * @param provider the OverviewProvider to remove. */ public void removeOverviewProvider(OverviewProvider provider) { @@ -425,7 +426,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Adds a ButtonPressedListener to be notified when the user presses the mouse button while over * this panel - * + * * @param listener the ButtonPressedListener to add. */ public void addButtonPressedListener(ButtonPressedListener listener) { @@ -436,7 +437,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Removes the given ButtonPressedListener. - * + * * @param listener the ButtonPressedListener to remove. */ public void removeButtonPressedListener(ButtonPressedListener listener) { @@ -508,7 +509,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Sets the divider location between the left margin areas and the main display. - * + * * @param dividerLocation the location to set on the divider. */ public void setDividerLocation(int dividerLocation) { @@ -556,7 +557,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Moves the cursor to the given program location and repositions the scrollbar to show that * location in the screen. - * + * * @param loc the location to move to. */ public boolean goTo(ProgramLocation loc) { @@ -574,6 +575,9 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc * screen will be scrolled only enough to show the cursor. */ public boolean goTo(ProgramLocation loc, boolean centerWhenNotVisible) { + + Swing.assertSwingThread("goTo() must be called on the Swing thread"); + final FieldLocation floc = getFieldLocation(loc); if (floc == null) { return false; @@ -623,9 +627,6 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc if (programAddressSpace != locAddressSpace) { FieldLocation compatibleLocation = getFieldLocationForDifferingAddressSpaces(loc, program); - if (compatibleLocation == null) { - return null; - } return compatibleLocation; } @@ -712,7 +713,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Positions the ListingPanel to the given address. - * + * * @param addr the address at which to position the listing. */ public boolean goTo(Address addr) { @@ -725,7 +726,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Positions the ListingPanel to the given address. - * + * * @param currentAddress used to determine which symbol to goto if the goto address has more * than one * @param gotoAddress the address at which to position to listing. @@ -768,7 +769,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Sets the program to be displayed by this listing panel - * + * * @param program the program to display. */ public void setProgram(Program program) { @@ -802,7 +803,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Restricts the program's view to the given address set - * + * * @param view the set of address to include in the view. */ public void setView(AddressSetView view) { @@ -875,7 +876,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Get a program location for the given point. - * + * * @return program location, or null if point does not correspond to a program location */ public ProgramLocation getProgramLocation(Point point) { @@ -911,7 +912,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Sets the cursor to the given program location. - * + * * @param loc the location at which to move the cursor. */ public void setCursorPosition(ProgramLocation loc) { @@ -920,10 +921,10 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Sets the cursor to the given program location with a given trigger - * + * * This method should only be used in automated testing to programmatically simulate a user * navigating within the listing panel. - * + * * @param loc the location at which to move the cursor. * @param trigger the event trigger */ @@ -1040,7 +1041,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Sets the selection. - * + * * @param sel the new selection */ public void setSelection(ProgramSelection sel) { @@ -1082,7 +1083,7 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Sets the highlight. - * + * * @param highlight the new highlight. */ public void setHighlight(ProgramSelection highlight) { @@ -1125,7 +1126,6 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc /** * Returns the currently selected text. The value will only be non-null for selections within a * single field. - * * @return the selected text or null */ public String getTextSelection() { diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/navigation/NavigationHistoryPluginTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/navigation/NavigationHistoryPluginTest.java index b02fb316a3..93d3f7e3d0 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/navigation/NavigationHistoryPluginTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/navigation/NavigationHistoryPluginTest.java @@ -37,7 +37,7 @@ import ghidra.program.model.listing.*; import ghidra.program.model.symbol.*; import ghidra.program.util.*; import ghidra.test.*; -import ghidra.util.task.TaskMonitorAdapter; +import ghidra.util.task.TaskMonitor; /** * Tests for tool state history plugin. @@ -87,7 +87,7 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration @After public void tearDown() throws Exception { - waitForPostedSwingRunnables(); + waitForSwing(); env.dispose(); } @@ -95,8 +95,7 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration public void testPrevious() throws Exception { // go to sscanf QueryData queryData = new QueryData("sscanf", false); - goToService.goToQuery(program.getMinAddress(), queryData, null, - TaskMonitorAdapter.DUMMY_MONITOR); + goToService.goToQuery(program.getMinAddress(), queryData, null, TaskMonitor.DUMMY); assertTrue(plugin.hasPrevious(navigatable)); @@ -119,30 +118,29 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration performAction(prevAction, provider, true); cb.updateNow(); - waitForPostedSwingRunnables(); + waitForSwing(); assertEquals(loc, cb.getCurrentLocation()); assertTrue(prevAction.isEnabledForContext(provider.getActionContext(null))); assertTrue(nextAction.isEnabledForContext(provider.getActionContext(null))); performAction(prevAction, provider, true); cb.updateNow(); - waitForPostedSwingRunnables(); + waitForSwing(); assertEquals(program.getMinAddress(), cb.getCurrentAddress()); - assertTrue(!prevAction.isEnabledForContext(provider.getActionContext(null))); + assertFalse(prevAction.isEnabledForContext(provider.getActionContext(null))); assertTrue(nextAction.isEnabledForContext(provider.getActionContext(null))); } @Test public void testNext() throws Exception { QueryData queryData = new QueryData("sscanf", false); - goToService.goToQuery(program.getMinAddress(), queryData, null, - TaskMonitorAdapter.DUMMY_MONITOR); + goToService.goToQuery(program.getMinAddress(), queryData, null, TaskMonitor.DUMMY); assertTrue(plugin.hasPrevious(navigatable)); assertNotNull(prevAction); assertTrue(prevAction.isEnabledForContext(provider.getActionContext(null))); - assertTrue(!nextAction.isEnabledForContext(provider.getActionContext(null))); + assertFalse(nextAction.isEnabledForContext(provider.getActionContext(null))); ProgramLocation loc = cb.getCurrentLocation(); assertTrue(loc instanceof FunctionSignatureFieldLocation); @@ -174,17 +172,17 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration performAction(prevAction, provider, true); cb.updateNow(); - waitForPostedSwingRunnables(); + waitForSwing(); assertEquals(opLoc, cb.getCurrentLocation()); performAction(prevAction, provider, true); cb.updateNow(); - waitForPostedSwingRunnables(); + waitForSwing(); assertEquals(xrefLoc, cb.getCurrentLocation()); performAction(prevAction, provider, true); cb.updateNow(); - waitForPostedSwingRunnables(); + waitForSwing(); assertEquals(loc, cb.getCurrentLocation()); assertTrue(prevAction.isEnabledForContext(provider.getActionContext(null))); @@ -192,18 +190,18 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration performAction(prevAction, provider, true); cb.updateNow(); - waitForPostedSwingRunnables(); + waitForSwing(); assertEquals(program.getMinAddress(), cb.getCurrentAddress()); - assertTrue(!prevAction.isEnabledForContext(provider.getActionContext(null))); + assertFalse(prevAction.isEnabledForContext(provider.getActionContext(null))); performAction(nextAction, provider, true); cb.updateNow(); - waitForPostedSwingRunnables(); + waitForSwing(); assertEquals(loc, cb.getCurrentLocation()); performAction(nextAction, provider, true); cb.updateNow(); - waitForPostedSwingRunnables(); + waitForSwing(); assertEquals(xrefLoc, cb.getCurrentLocation()); assertTrue(prevAction.isEnabledForContext(provider.getActionContext(null))); @@ -211,24 +209,23 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration performAction(prevAction, provider, true); performAction(prevAction, provider, true); - assertTrue(!prevAction.isEnabledForContext(provider.getActionContext(null))); + assertFalse(prevAction.isEnabledForContext(provider.getActionContext(null))); assertTrue(nextAction.isEnabledForContext(provider.getActionContext(null))); for (ProgramLocation element : locations) { performAction(nextAction, provider, true); cb.updateNow(); - waitForPostedSwingRunnables(); + waitForSwing(); assertEquals(element, cb.getCurrentLocation()); } - assertTrue(!nextAction.isEnabledForContext(provider.getActionContext(null))); + assertFalse(nextAction.isEnabledForContext(provider.getActionContext(null))); } @Test public void testNavigationInCodeBrowser() throws Exception { QueryData queryData = new QueryData("sscanf", false); - goToService.goToQuery(program.getMinAddress(), queryData, null, - TaskMonitorAdapter.DUMMY_MONITOR); + goToService.goToQuery(program.getMinAddress(), queryData, null, TaskMonitor.DUMMY); ProgramLocation loc = cb.getCurrentLocation(); assertTrue(loc instanceof FunctionSignatureFieldLocation); @@ -279,8 +276,7 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration DockingActionIf clearAction = getAction(nextPrevPlugin, "Clear History Buffer"); QueryData queryData = new QueryData("sscanf", false); - goToService.goToQuery(program.getMinAddress(), queryData, null, - TaskMonitorAdapter.DUMMY_MONITOR); + goToService.goToQuery(program.getMinAddress(), queryData, null, TaskMonitor.DUMMY); ProgramLocation loc = cb.getCurrentLocation(); @@ -294,8 +290,8 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration click(cb, 2); performAction(clearAction, provider, true); - assertTrue(!plugin.hasNext(navigatable)); - assertTrue(!plugin.hasPrevious(navigatable)); + assertFalse(plugin.hasNext(navigatable)); + assertFalse(plugin.hasPrevious(navigatable)); } @Test @@ -303,14 +299,13 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration ProgramLocation initialLoc = cb.getCurrentLocation(); QueryData queryData = new QueryData("sscanf", false); - goToService.goToQuery(program.getMinAddress(), queryData, null, - TaskMonitorAdapter.DUMMY_MONITOR); + goToService.goToQuery(program.getMinAddress(), queryData, null, TaskMonitor.DUMMY); assertTrue(plugin.hasPrevious(navigatable)); assertNotNull(prevAction); assertTrue(prevAction.isEnabledForContext(provider.getActionContext(null))); - assertTrue(!nextAction.isEnabledForContext(provider.getActionContext(null))); + assertFalse(nextAction.isEnabledForContext(provider.getActionContext(null))); ProgramLocation loc = cb.getCurrentLocation(); assertTrue(loc instanceof FunctionSignatureFieldLocation); @@ -347,10 +342,10 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration for (int i = locations.length - 1; i >= 0; i--) { performAction(prevAction, provider, true); cb.updateNow(); - waitForPostedSwingRunnables(); + waitForSwing(); assertEquals(locations[i], cb.getCurrentLocation()); } - assertTrue(!prevAction.isEnabledForContext(provider.getActionContext(null))); + assertFalse(prevAction.isEnabledForContext(provider.getActionContext(null))); } @Test @@ -367,16 +362,17 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration ++count; - goToService.goTo(currentAddr, symbol.getAddress()); + Address addr = currentAddr; + runSwing(() -> goToService.goTo(addr, symbol.getAddress())); cb.updateNow(); currentAddr = symbol.getAddress(); if (count > NavigationHistoryPlugin.MAX_HISTORY_SIZE) { for (int i = 0; i < NavigationHistoryPlugin.MAX_HISTORY_SIZE - 1; i++) { assertTrue(plugin.hasPrevious(navigatable)); - plugin.previous(navigatable); + runSwing(() -> plugin.previous(navigatable)); cb.updateNow(); } - assertTrue(!plugin.hasPrevious(navigatable)); + assertFalse(plugin.hasPrevious(navigatable)); break; } } @@ -396,7 +392,8 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration } ++count; - goToService.goTo(currentAddr, symbol.getAddress()); + Address addr = currentAddr; + runSwing(() -> goToService.goTo(addr, symbol.getAddress())); cb.updateNow(); currentAddr = symbol.getAddress(); if (count > 2 * NavigationHistoryPlugin.MAX_HISTORY_SIZE) { @@ -413,16 +410,16 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration for (int i = 0; i < NavigationHistoryPlugin.MAX_HISTORY_SIZE - 1; i++) { assertTrue(plugin.hasPrevious(navigatable)); - plugin.previous(navigatable); + runSwing(() -> plugin.previous(navigatable)); cb.updateNow(); } - assertTrue(!plugin.hasPrevious(navigatable)); + assertFalse(plugin.hasPrevious(navigatable)); } @Test public void testNextAfterUndoRedo() throws Exception { // - // Note: the addresses used here are arbitrary, except that there is an undefined are + // Note: the addresses used here are arbitrary, except that there is an undefined are // we can use to create data // @@ -448,7 +445,7 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration ProgramLocation loc = cb.getCurrentLocation(); assertEquals(addr, loc.getAddress()); - // do the next action and make sure it went to 1001020, which is + // do the next action and make sure it went to 1001020, which is // where we were before the undo performAction(prevAction, provider, true); cb.updateNow(); @@ -459,7 +456,7 @@ public class NavigationHistoryPluginTest extends AbstractGhidraHeadedIntegration Address addr3 = getAddr(0x1001030); goToService.goTo(addr3); - // do the redo and verify we are back to 1001020, which is + // do the redo and verify we are back to 1001020, which is // where we were when we did the undo performAction(redoAction, provider, true); cb.updateNow(); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/select/qualified/QualifiedSelectionPluginTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/select/qualified/QualifiedSelectionPluginTest.java index 7e85b64e0c..7232b609f8 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/select/qualified/QualifiedSelectionPluginTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/select/qualified/QualifiedSelectionPluginTest.java @@ -25,7 +25,6 @@ import javax.swing.tree.TreePath; import org.junit.*; -import docking.ComponentProvider; import docking.action.DockingActionIf; import ghidra.app.events.ProgramSelectionPluginEvent; import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin; @@ -33,6 +32,7 @@ import ghidra.app.plugin.core.codebrowser.CodeViewerProvider; import ghidra.app.plugin.core.marker.MarkerManagerPlugin; import ghidra.app.plugin.core.navigation.GoToAddressLabelPlugin; import ghidra.app.plugin.core.programtree.ProgramTreePlugin; +import ghidra.app.plugin.core.programtree.ViewManagerComponentProvider; import ghidra.app.plugin.core.select.programtree.ProgramTreeSelectionPlugin; import ghidra.app.services.ProgramManager; import ghidra.framework.plugintool.PluginTool; @@ -57,7 +57,7 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio private DockingActionIf selectInstructionAction; private DockingActionIf selectUndefinedAction; private ProgramTreePlugin pt; - private ComponentProvider programTreeProvider; + private ViewManagerComponentProvider programTreeProvider; private DockingActionIf replaceView; private ToyProgramBuilder builder; @@ -94,10 +94,9 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio } private void showProgramTree() { - - ProgramTreePlugin ptree = env.getPlugin(ProgramTreePlugin.class); - programTreeProvider = (ComponentProvider) getInstanceField("viewProvider", pt); + programTreeProvider = (ViewManagerComponentProvider) getInstanceField("viewProvider", pt); tool.showComponentProvider(programTreeProvider, true); + waitForComponentProvider(ViewManagerComponentProvider.class); } protected void setUpQualifiedSelection(PluginTool tool) throws Exception { @@ -115,7 +114,7 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio // Select All Instructions. performAction(selectInstructionAction, provider, true); ProgramSelection instructionSet = getCurrentSelection(); - assertTrue(!instructionSet.isEmpty()); + assertFalse(instructionSet.isEmpty()); // Select No Data (because there is a selection of all instructions). performAction(selectDataAction, provider, true); @@ -124,7 +123,7 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio // Select All Data. performAction(selectDataAction, provider, true); ProgramSelection dataSet = getCurrentSelection(); - assertTrue(!dataSet.isEmpty()); + assertFalse(dataSet.isEmpty()); // Select No Undefined. performAction(selectUndefinedAction, provider, true); @@ -133,7 +132,7 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio // Select All Undefined. performAction(selectUndefinedAction, provider, true); ProgramSelection undefinedSet = getCurrentSelection(); - assertTrue(!undefinedSet.isEmpty()); + assertFalse(undefinedSet.isEmpty()); // Select No Instructions. performAction(selectInstructionAction, provider, true); @@ -170,7 +169,7 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio // Select Instructions. performAction(selectInstructionAction, provider, true); ProgramSelection instructionSet = getCurrentSelection(); - assertTrue(!instructionSet.isEmpty()); + assertFalse(instructionSet.isEmpty()); assertTrue(instructionSet.getMinAddress().compareTo(addr("010012d2")) >= 0); assertTrue(instructionSet.getMaxAddress().compareTo(addr("01001960")) <= 0); @@ -182,7 +181,7 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio performAction(selectDataAction, provider, true); waitForSwing(); ProgramSelection dataSet = getCurrentSelection(); - assertTrue(!dataSet.isEmpty()); + assertFalse(dataSet.isEmpty()); assertTrue(dataSet.getMinAddress().compareTo(addr("010012d2")) >= 0); assertTrue(dataSet.getMaxAddress().compareTo(addr("01001960")) <= 0); @@ -194,7 +193,7 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio performAction(selectUndefinedAction, provider, true); waitForSwing(); ProgramSelection undefinedSet = getCurrentSelection(); - assertTrue(!undefinedSet.isEmpty()); + assertFalse(undefinedSet.isEmpty()); assertTrue(undefinedSet.getMinAddress().compareTo(addr("010012d2")) >= 0); assertTrue(undefinedSet.getMaxAddress().compareTo(addr("01001960")) <= 0); @@ -219,7 +218,8 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio @Test public void testSelectWithView() throws Exception { AddressSet rsrcSet = new AddressSet(addr("0100a000"), addr("0100f3ff")); - JTree tree = findComponent(tool.getToolFrame(), JTree.class); + + JTree tree = waitFor(() -> findComponent(tool.getToolFrame(), JTree.class)); // Replace view with .rsrc selectTreeNodeByText(tree, ".rsrc", true); @@ -254,12 +254,12 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio performAction(selectDataAction, provider, true); waitForSwing(); ProgramSelection rsrcDataSet = getCurrentSelection(); - assertTrue(!rsrcDataSet.isEmpty()); + assertFalse(rsrcDataSet.isEmpty()); // Change to program view selectTreeNodeByText(tree, "Test", true); performAction(replaceView, provider, true); ProgramSelection dataSet = getCurrentSelection(); - assertTrue(!dataSet.isEmpty()); + assertFalse(dataSet.isEmpty()); // Select No Undefined. performAction(selectUndefinedAction, provider, true); @@ -274,12 +274,12 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio performAction(selectUndefinedAction, provider, true); waitForSwing(); ProgramSelection rsrcUndefinedSet = getCurrentSelection(); - assertTrue(!rsrcUndefinedSet.isEmpty()); + assertFalse(rsrcUndefinedSet.isEmpty()); // Change to program view selectTreeNodeByText(tree, "Test", true); performAction(replaceView, provider, true); ProgramSelection undefinedSet = getCurrentSelection(); - assertTrue(!undefinedSet.isEmpty()); + assertFalse(undefinedSet.isEmpty()); // Select No Instructions. performAction(selectInstructionAction, provider, true); @@ -396,9 +396,6 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio }, wait); } - /** - * @param instructionSet - */ private void checkForInstructions(ProgramSelection instructionSet) { Listing listing = program.getListing(); AddressIterator iter = instructionSet.getAddresses(true); @@ -409,9 +406,6 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio } } - /** - * @param dataSet - */ private void checkForDefinedData(ProgramSelection dataSet) { Listing listing = program.getListing(); AddressIterator iter = dataSet.getAddresses(true); @@ -422,9 +416,6 @@ public class QualifiedSelectionPluginTest extends AbstractGhidraHeadedIntegratio } } - /** - * @param undefinedSet - */ private void checkForUndefined(ProgramSelection undefinedSet) { Listing listing = program.getListing(); AddressIterator iter = undefinedSet.getAddresses(true); diff --git a/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/functioncompare/CompareFunctionsSlowTest.java b/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/functioncompare/CompareFunctionsSlowTest.java index c66f6f9cb8..c53dc39dca 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/functioncompare/CompareFunctionsSlowTest.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/functioncompare/CompareFunctionsSlowTest.java @@ -169,14 +169,13 @@ public class CompareFunctionsSlowTest extends AbstractGhidraHeadedIntegrationTes clickComponentProvider(provider); DockingActionIf openTableAction = getAction(plugin, "Add Functions To Comparison"); - performAction(openTableAction, false); + performAction(openTableAction, provider, false); Window selectWindow = waitForWindowByTitleContaining("Select Functions"); assertNotNull(selectWindow); selectWindow.setVisible(false); } - @SuppressWarnings("unchecked") @Test public void testAddFunctionToExistingCompare() { Set functions = CompareFunctionsTestUtility.getFunctionsAsSet(foo); @@ -189,10 +188,12 @@ public class CompareFunctionsSlowTest extends AbstractGhidraHeadedIntegrationTes assertTrue(provider.getModel().getSourceFunctions().contains(foo)); DockingActionIf openTableAction = getAction(plugin, "Add Functions To Comparison"); - performAction(openTableAction, false); + performAction(openTableAction, provider, false); + @SuppressWarnings("unchecked") TableSelectionDialog chooser = waitForDialogComponent(TableSelectionDialog.class); + @SuppressWarnings("unchecked") GFilterTable table = (GFilterTable) getInstanceField("gFilterTable", chooser);