GP-2184 - removed JMockit usage from some tests (part 4)

This commit is contained in:
dragonmacher 2022-06-15 12:29:13 -04:00
parent 0e3fe30c67
commit 3ac7ecdb13
4 changed files with 107 additions and 58 deletions

View File

@ -190,7 +190,7 @@ public class GoToHelper {
* @return true if navigation was successful or a list of possible linkage locations
* was displayed.
*/
private boolean goToExternalLinkage(Navigatable nav, ExternalLocation externalLoc,
protected boolean goToExternalLinkage(Navigatable nav, ExternalLocation externalLoc,
boolean popupAllowed) {
if (externalLoc == null) {
return false;
@ -457,10 +457,6 @@ public class GoToHelper {
private Program findGoToProgram(Program currentProgram, Address address) {
// we need to try and find a suitable program
Program goToProgram = findProgramContaining(currentProgram, address);
if (goToProgram == null) {
return null;
}
return goToProgram;
}

View File

@ -15,7 +15,7 @@
*/
package ghidra.test;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.*;
import java.io.File;
import java.io.IOException;
@ -601,6 +601,11 @@ public abstract class AbstractGhidraHeadlessIntegrationTest extends AbstractDock
}
}
T instance = tool.getService(service);
if (instance != null) {
serviceManager.removeService(service, instance);
}
set.add(replacement.getClass());
serviceManager.addService(service, replacement);

View File

@ -17,6 +17,8 @@ package ghidra.app.plugin.core.decompile;
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
@ -29,14 +31,16 @@ import ghidra.app.actions.AbstractFindReferencesDataTypeAction;
import ghidra.app.actions.AbstractFindReferencesToAddressAction;
import ghidra.app.nav.Navigatable;
import ghidra.app.plugin.core.decompile.actions.FindReferencesToHighSymbolAction;
import ghidra.app.plugin.core.navigation.FindAppliedDataTypesService;
import ghidra.app.plugin.core.navigation.locationreferences.LocationReferencesProvider;
import ghidra.app.plugin.core.navigation.locationreferences.LocationReferencesService;
import ghidra.app.services.*;
import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.Program;
import ghidra.program.util.ProgramLocation;
import ghidra.util.HelpLocation;
import ghidra.util.task.TaskMonitor;
import mockit.*;
import mockit.Mock;
public abstract class AbstractDecompilerFindReferencesActionTest extends AbstractDecompilerTest {
@ -44,8 +48,7 @@ public abstract class AbstractDecompilerFindReferencesActionTest extends Abstrac
protected DockingActionIf findReferencesToSymbolAction;
protected DockingActionIf findReferencesToAddressAction;
protected SpyDataTypeReferenceFinder<DataTypeReferenceFinder> spyReferenceFinder;
protected SpyLocationReferencesService<LocationReferencesService> spyLocationReferenceService;
protected SpyLocationReferencesService spyLocationReferenceService;
@Override
@Before
@ -63,18 +66,37 @@ public abstract class AbstractDecompilerFindReferencesActionTest extends Abstrac
private void installSpyDataTypeReferenceFinder() {
spyReferenceFinder = new SpyDataTypeReferenceFinder<>();
replaceService(tool, DataTypeReferenceFinder.class, new StubDataTypeReferenceFinder());
//
// We replace services in order for us to spy on system internals. This gets tricky
// because the LocationReferencesPlugin installs 2 services. So, when we replace it, we
// lose both of it services. We only want to replace one of the services, so we have to
// re-install the plugin to be the service provider for the service we still need.
//
FindAppliedDataTypesService fadService = tool.getService(FindAppliedDataTypesService.class);
replaceService(tool, DataTypeReferenceFinder.class, new SpyDataTypeReferenceFinder());
spyLocationReferenceService = new SpyLocationReferencesService<>();
LocationReferencesService lrService = tool.getService(LocationReferencesService.class);
spyLocationReferenceService = new SpyLocationReferencesService(lrService);
replaceService(tool, LocationReferencesService.class, spyLocationReferenceService);
// as noted above, put back this service implementation
replaceService(tool, FindAppliedDataTypesService.class, fadService);
}
protected void assertFindAllReferencesToCompositeFieldWasCalled() {
int last = SpyDataTypeReferenceFinder.instances.size() - 1;
SpyDataTypeReferenceFinder spyReferenceFinder =
SpyDataTypeReferenceFinder.instances.get(last);
assertEquals(1, spyReferenceFinder.getFindCompositeFieldReferencesCallCount());
assertEquals(0, spyReferenceFinder.getFindDataTypeReferencesCallCount());
}
protected void assertFindAllReferencesToDataTypeWasCalled() {
int last = SpyDataTypeReferenceFinder.instances.size() - 1;
SpyDataTypeReferenceFinder spyReferenceFinder =
SpyDataTypeReferenceFinder.instances.get(last);
assertEquals(0, spyReferenceFinder.getFindCompositeFieldReferencesCallCount());
assertEquals(1, spyReferenceFinder.getFindDataTypeReferencesCallCount());
}
@ -152,11 +174,21 @@ public abstract class AbstractDecompilerFindReferencesActionTest extends Abstrac
findReferencesAction.isAddToPopup(context));
}
public class SpyDataTypeReferenceFinder<T extends DataTypeReferenceFinder> extends MockUp<T> {
public static class SpyDataTypeReferenceFinder implements DataTypeReferenceFinder {
private static List<SpyDataTypeReferenceFinder> instances = new ArrayList<>();
private AtomicInteger dataTypeReferencesCallCount = new AtomicInteger();
private AtomicInteger compositeFieldReferencesCallCount = new AtomicInteger();
public SpyDataTypeReferenceFinder() {
// Instances of this class are created by ReferenceUtils via the ClassSearcher. Save
// the instances so we can use the spy in the test
instances.add(this);
}
@Override
@Mock
public void findReferences(Program p, DataType dataType,
Consumer<DataTypeReference> callback, TaskMonitor monitor) {
@ -164,6 +196,7 @@ public abstract class AbstractDecompilerFindReferencesActionTest extends Abstrac
dataTypeReferencesCallCount.incrementAndGet();
}
@Override
@Mock
public void findReferences(Program p, DataType dt, String fieldName,
Consumer<DataTypeReference> callback, TaskMonitor monitor) {
@ -171,6 +204,7 @@ public abstract class AbstractDecompilerFindReferencesActionTest extends Abstrac
compositeFieldReferencesCallCount.incrementAndGet();
}
@Override
@Mock
public void findReferences(Program p, FieldMatcher fieldMatcher,
Consumer<DataTypeReference> callback, TaskMonitor monitor) {
@ -193,20 +227,30 @@ public abstract class AbstractDecompilerFindReferencesActionTest extends Abstrac
}
}
public class SpyLocationReferencesService<T extends LocationReferencesService>
extends MockUp<T> {
public class SpyLocationReferencesService implements LocationReferencesService {
private AtomicInteger showReferencesCallCount = new AtomicInteger();
private LocationReferencesService lrService;
@Mock
public void showReferencesToLocation(Invocation invocation, ProgramLocation location,
Navigatable navigatable) {
public SpyLocationReferencesService(LocationReferencesService lrService) {
this.lrService = lrService;
}
@Override
public void showReferencesToLocation(ProgramLocation location, Navigatable navigatable) {
showReferencesCallCount.incrementAndGet();
invocation.proceed(location, navigatable);
lrService.showReferencesToLocation(location, navigatable);
}
public int getShowReferencesCallCount() {
return showReferencesCallCount.get();
}
@Override
public HelpLocation getHelpLocation() {
return null;
}
}
}

View File

@ -28,13 +28,14 @@ import ghidra.app.plugin.core.codebrowser.CodeViewerProvider;
import ghidra.app.plugin.core.gotoquery.GoToHelper;
import ghidra.app.plugin.core.navigation.NavigationOptions;
import ghidra.app.plugin.core.navigation.NextPrevAddressPlugin;
import ghidra.app.services.GoToService;
import ghidra.app.util.navigation.GoToServiceImpl;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.*;
import ghidra.program.util.OperandFieldLocation;
import ghidra.program.util.ProgramLocation;
import ghidra.test.ClassicSampleX86ProgramBuilder;
import mockit.*;
public class DecompilerNavigationTest extends AbstractDecompilerTest {
@ -49,6 +50,23 @@ public class DecompilerNavigationTest extends AbstractDecompilerTest {
tool.showComponentProvider(cbProvider, true);
}
private void installSpyGoToHelper() {
GoToHelper spyGoToHelper = new GoToHelper(tool) {
@Override
protected boolean goToExternalLinkage(Navigatable nav, ExternalLocation externalLoc,
boolean popupAllowed) {
goToExternalLinkageCalled = true;
return super.goToExternalLinkage(nav, externalLoc, popupAllowed);
}
};
GoToServiceImpl goToServiceImpl = (GoToServiceImpl) tool.getService(GoToService.class);
setInstanceField("helper", goToServiceImpl, spyGoToHelper);
}
@Override
protected Program getProgram() throws Exception {
return buildProgram();
@ -94,8 +112,7 @@ public class DecompilerNavigationTest extends AbstractDecompilerTest {
public void testFunctionNavigation_ExternalProgramFunction_OptionNavigateToExternal()
throws Exception {
// this call triggers jMockit to load our spy
new SpyGoToHelper();
installSpyGoToHelper();
tool.getOptions("Navigation")
.setEnum("External Navigation",
@ -130,8 +147,7 @@ public class DecompilerNavigationTest extends AbstractDecompilerTest {
public void testFunctionNavigation_ExternalProgramFunction_OptionNavigateToLinkage()
throws Exception {
// this call triggers jMockit to load our spy
new SpyGoToHelper();
installSpyGoToHelper();
tool.getOptions("Navigation")
.setEnum("External Navigation",
@ -178,8 +194,7 @@ public class DecompilerNavigationTest extends AbstractDecompilerTest {
}
@Test
public void testFunctionNavigation_WithAViewThatCachesTheLastValidFunction()
throws Exception {
public void testFunctionNavigation_WithAViewThatCachesTheLastValidFunction() throws Exception {
//
// This is testing the case where the user starts on a function foo(). Ancillary windows
@ -282,15 +297,4 @@ public class DecompilerNavigationTest extends AbstractDecompilerTest {
program.flushEvents();
waitForSwing();
}
public class SpyGoToHelper extends MockUp<GoToHelper> {
@Mock
private boolean goToExternalLinkage(Invocation invocation, Navigatable nav,
ExternalLocation externalLoc, boolean popupAllowed) {
goToExternalLinkageCalled = true;
return invocation.proceed(nav, externalLoc, popupAllowed);
}
}
}