GP-2168 - removed JMockit usage from some tests

This commit is contained in:
dragonmacher 2022-06-14 14:52:29 -04:00
parent f02ecf21ca
commit 33ed42dcb7
13 changed files with 92 additions and 116 deletions

View file

@ -309,6 +309,12 @@ public class DecompilerController {
//@formatter:on
}
// for testing
void setCache(Cache<Function, DecompileResults> cache) {
this.decompilerCache.invalidateAll();
this.decompilerCache = cache;
}
public void clearCache() {
decompilerCache.invalidateAll();
}

View file

@ -15,8 +15,7 @@
*/
package ghidra.app.decompiler.component;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;
import java.util.*;
import java.util.Map.Entry;
@ -43,14 +42,11 @@ import ghidra.program.model.listing.Function;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.util.ProgramLocation;
import ghidra.test.*;
import mockit.Mock;
import mockit.MockUp;
public class DecompilerCachingTest extends AbstractGhidraHeadedIntegrationTest {
private TestEnv env;
private PluginTool tool;
private DecompilePlugin decompilePlugin;
private CodeBrowserPlugin codeBrowser;
private ProgramDB program;
private List<Address> functionAddrs = new ArrayList<>();
@ -58,10 +54,15 @@ public class DecompilerCachingTest extends AbstractGhidraHeadedIntegrationTest {
public Cache<Function, DecompileResults> cache;
private ToyProgramBuilder builder;
// partial fake of DecompilerController to take control of the buildCache() method.
public class FakeDecompilerController extends MockUp<DecompilerController> {
@Mock
public Cache<Function, DecompileResults> buildCache() {
@Before
public void setUp() throws Exception {
setErrorGUIEnabled(false);
env = new TestEnv();
tool = env.getTool();
initializeTool();
//@formatter:off
cache = CacheBuilder
.newBuilder()
@ -70,22 +71,9 @@ public class DecompilerCachingTest extends AbstractGhidraHeadedIntegrationTest {
.build()
;
//@formatter:on
return cache;
}
}
@Before
public void setUp() throws Exception {
// the magic of JMockit will cause our FakeDecompilerController to get used instead
// of the real one, regardless of where it gets constructed.
new FakeDecompilerController();
setErrorGUIEnabled(false);
env = new TestEnv();
tool = env.getTool();
initializeTool();
DecompilerController controller = decompilerProvider.getController();
controller.setCache(cache);
}
@After
@ -258,8 +246,6 @@ public class DecompilerCachingTest extends AbstractGhidraHeadedIntegrationTest {
private void installPlugins() throws PluginException {
tool.addPlugin(CodeBrowserPlugin.class.getName());
tool.addPlugin(DecompilePlugin.class.getName());
decompilePlugin = env.getPlugin(DecompilePlugin.class);
codeBrowser = env.getPlugin(CodeBrowserPlugin.class);
}

View file

@ -21,6 +21,7 @@ import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.function.BiConsumer;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;
@ -85,6 +86,9 @@ public class FGController implements ProgramLocationListener, ProgramSelectionLi
string -> provider.setClipboardStringContent(string);
private Cache<Function, FGData> cache;
private BiConsumer<FGData, Boolean> fgDataDisposeListener = (data, evicted) -> {
// dummy
};
public FGController(FGProvider provider, FunctionGraphPlugin plugin) {
this.provider = provider;
@ -110,6 +114,7 @@ public class FGController implements ProgramLocationListener, ProgramSelectionLi
}
data.dispose();
fgDataDisposeListener.accept(data, true);
return true;
}
@ -882,6 +887,7 @@ public class FGController implements ProgramLocationListener, ProgramSelectionLi
Function function = data.getFunction();
if (function != null && cache.getIfPresent(function) != data) {
data.dispose();
fgDataDisposeListener.accept(data, false);
return true;
}
return false;
@ -1040,10 +1046,23 @@ public class FGController implements ProgramLocationListener, ProgramSelectionLi
//@formatter:on
}
private void cacheValueRemoved(RemovalNotification<Function, FGData> notification) {
// for testing
void setCache(Cache<Function, FGData> cache) {
this.cache.invalidateAll();
this.cache = cache;
}
// open for testing
void cacheValueRemoved(RemovalNotification<Function, FGData> notification) {
disposeGraphDataIfNotInUse(notification.getValue());
}
void setFGDataDisposedListener(BiConsumer<FGData, Boolean> listener) {
this.fgDataDisposeListener = listener != null ? listener : (data, evicted) -> {
// dummy
};
}
//==================================================================================================
// Inner Classes
//==================================================================================================

View file

@ -101,6 +101,6 @@ public class FGData {
@Override
public String toString() {
return "FunctionGraphData[" + function.getName() + "]";
return "FunctionGraphData[" + function.getName() + "@" + function.getEntryPoint() + "]";
}
}

View file

@ -33,7 +33,6 @@ import org.junit.*;
import docking.*;
import docking.action.*;
import docking.menu.ActionState;
import docking.menu.MultiStateDockingAction;
import docking.test.AbstractDockingTest;
import docking.widgets.EventTrigger;
@ -75,7 +74,6 @@ import ghidra.program.util.ProgramLocation;
import ghidra.program.util.ProgramSelection;
import ghidra.test.*;
import ghidra.util.Msg;
import ghidra.util.exception.AssertException;
import ghidra.util.task.RunManager;
public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedIntegrationTest {
@ -541,13 +539,13 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
protected void waitForBusyRunManager(FGController controller) {
FGModel model = controller.getModel();
long start = System.nanoTime();
// long start = System.nanoTime();
waitForSwing();
RunManager runManager = (RunManager) TestUtils.getInstanceField("runManager", model);
waitForCondition(() -> !runManager.isInProgress());
long end = System.nanoTime();
long total = end - start;
// long end = System.nanoTime();
// long total = end - start;
// Msg.debug(this,
// "Run manager wait time: " + TimeUnit.MILLISECONDS.convert(total, TimeUnit.NANOSECONDS));
}
@ -1999,26 +1997,6 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
waitForSwing();
}
private void setMinCrossLayout() {
Object actionManager = getInstanceField("actionManager", graphProvider);
@SuppressWarnings("unchecked")
final MultiStateDockingAction<FGLayoutProvider> action =
(MultiStateDockingAction<FGLayoutProvider>) getInstanceField("layoutAction",
actionManager);
runSwing(() -> {
List<ActionState<FGLayoutProvider>> states = action.getAllActionStates();
for (ActionState<FGLayoutProvider> state : states) {
FGLayoutProvider layoutProvider = state.getUserData();
if (layoutProvider.getLayoutName().contains("MinCross")) {
action.setCurrentActionState(state);
return;
}
}
throw new AssertException("Unable to find MinCross layout");
});
}
protected FGData triggerPersistenceAndReload(String functionAddress) {
//
// Ideally, we would like to save, close and re-open the program so that we can get

View file

@ -19,6 +19,8 @@ import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
import ghidra.app.plugin.core.functiongraph.mvc.FunctionGraphCacheTest;
//@formatter:off
@RunWith(Suite.class)
@SuiteClasses({

View file

@ -13,10 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.plugin.core.functiongraph;
package ghidra.app.plugin.core.functiongraph.mvc;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;
import java.util.*;
@ -25,23 +24,28 @@ import org.junit.Test;
import com.google.common.cache.*;
import ghidra.app.plugin.core.functiongraph.mvc.FGController;
import ghidra.app.plugin.core.functiongraph.mvc.FGData;
import ghidra.app.plugin.core.functiongraph.AbstractFunctionGraphTest;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Function;
import mockit.*;
public class FunctionGraphCacheTest extends AbstractFunctionGraphTest {
private Cache<Function, FGData> cache;
private List<Address> disposedFunctionData = Collections.synchronizedList(new ArrayList<>());
private List<Address> evictedFromCache = Collections.synchronizedList(new ArrayList<>());
// partial fake of FGController to take control of the buildCache() method and spy
// on the two methods that might dispose a FunctionGrahpData object.
public class FakeFunctionGraphController extends MockUp<FGController> {
@Override
@Before
public void setUp() throws Exception {
super.setUp();
@Mock
public Cache<Function, FGData> buildCache(RemovalListener<Function, FGData> listener) {
FGController controller = getFunctionGraphController();
// go to an function address that is not used by this test (all tests use functions 0-2)
goToAddress(functionAddrs.get(3));
controller.clear();
waitForSwing();
RemovalListener<Function, FGData> listener = controller::cacheValueRemoved;
//@formatter:off
cache = CacheBuilder
@ -52,42 +56,21 @@ public class FunctionGraphCacheTest extends AbstractFunctionGraphTest {
.build()
;
//@formatter:on
return cache;
}
@Mock
boolean disposeIfNotInCache(Invocation invocation, FGData data) {
boolean result = invocation.proceed(data);
controller.setCache(cache);
controller.setFGDataDisposedListener((data, evicted) -> {
Function function = data.getFunction();
if (function == null) {
return result;
return;
}
Address address = data.getFunction().getEntryPoint();
if (result) {
disposedFunctionData.add(address);
if (evicted) {
evictedFromCache.add(address);
}
return result;
}
});
@Mock
boolean disposeGraphDataIfNotInUse(Invocation invocation, FGData data) {
boolean result = invocation.proceed(data);
evictedFromCache.add(data.getFunction().getEntryPoint());
if (result) {
disposedFunctionData.add(data.getFunction().getEntryPoint());
}
return result;
}
}
@Override
@Before
public void setUp() throws Exception {
// the magic of JMockit will cause our FakeDecompilerController to get used instead
// of the real one, regardless of where it gets constructed.
new FakeFunctionGraphController();
super.setUp();
goToAddress(getStartingAddress());
}
@Test
@ -103,6 +86,7 @@ public class FunctionGraphCacheTest extends AbstractFunctionGraphTest {
@Test
public void testBackToOldFunctionIsCacheHit() {
goToAddress(functionAddrs.get(0));
goToAddress(functionAddrs.get(1));
CacheStats stats1 = cache.stats();
@ -141,10 +125,11 @@ public class FunctionGraphCacheTest extends AbstractFunctionGraphTest {
goToAddress(functionAddrs.get(0));
goToAddress(functionAddrs.get(1));
goToAddress(functionAddrs.get(2));
assertEquals(3, cache.size());
cache.invalidateAll();
assertEquals(3, evictedFromCache.size());
assertEquals(2, evictedFromCache.size());
assertEquals(2, disposedFunctionData.size());
assertTrue(disposedFunctionData.contains(getAddress(functionAddrs.get(0))));
assertTrue(disposedFunctionData.contains(getAddress(functionAddrs.get(1))));