From 4919d6ec54a0975e687b46758f426894567a083c Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Tue, 11 Jun 2019 10:46:46 -0400 Subject: [PATCH] Tests - fix for threading issue involving weakly consistent cache --- .../component/DecompilerCachingTest.java | 16 +++++----- .../main/java/generic/test/AbstractGTest.java | 30 +++++++++++++++++-- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/decompiler/component/DecompilerCachingTest.java b/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/decompiler/component/DecompilerCachingTest.java index 8a8c5c44a4..54a765a8ff 100644 --- a/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/decompiler/component/DecompilerCachingTest.java +++ b/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/decompiler/component/DecompilerCachingTest.java @@ -15,11 +15,13 @@ */ package ghidra.app.decompiler.component; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.util.*; import java.util.Map.Entry; import java.util.concurrent.ConcurrentMap; +import java.util.function.Supplier; import org.junit.*; @@ -225,20 +227,20 @@ public class DecompilerCachingTest extends AbstractGhidraHeadedIntegrationTest { } private void assertCacheSize(int expected) { - long actual = cache.size(); - if (expected == actual) { - return; - } + Supplier supplier = () -> getCacheSizeFailureMessage(expected); + waitForCondition(() -> cache.size() == expected, supplier); + } + private String getCacheSizeFailureMessage(int expected) { StringBuilder buffy = new StringBuilder("Cache size is not as expected - expected " + - expected + "; found " + actual + "\nEntries in cache:\n"); + expected + "; found " + cache.size() + "\nEntries in cache:\n"); ConcurrentMap map = cache.asMap(); Set> entries = map.entrySet(); for (Entry entry : entries) { Function key = entry.getKey(); buffy.append('\t').append(key.getName()).append('\n'); } - fail(buffy.toString()); + return buffy.toString(); } private void buildDummyFunction(ToyProgramBuilder programBuilder, String functionName, diff --git a/Ghidra/Framework/Generic/src/main/java/generic/test/AbstractGTest.java b/Ghidra/Framework/Generic/src/main/java/generic/test/AbstractGTest.java index 66757b9c8f..6f69be081e 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/test/AbstractGTest.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/test/AbstractGTest.java @@ -393,6 +393,20 @@ public abstract class AbstractGTest { waitForCondition(condition, true /*failOnTimeout*/, failureMessage); } + /** + * Waits for the given condition to return true + * + * @param condition the condition that returns true when satisfied + * @param failureMessageSupplier the function that will supply the failure message in the + * event of a timeout. + * @throws AssertionFailedError if the condition is not met within the timeout period + */ + public static void waitForCondition(BooleanSupplier condition, + Supplier failureMessageSupplier) throws AssertionFailedError { + + waitForCondition(condition, true /*failOnTimeout*/, failureMessageSupplier); + } + /** * Waits for the given condition to return true. Most of the waitForCondition() * methods throw an {@link AssertionFailedError} if the timeout period expires. @@ -403,12 +417,18 @@ public abstract class AbstractGTest { * @param supplier the supplier that returns true when satisfied */ public static void waitForConditionWithoutFailing(BooleanSupplier supplier) { - waitForCondition(supplier, false /*failOnTimeout*/, null /*failure message*/); + waitForCondition(supplier, false /*failOnTimeout*/, () -> null /*failure message*/); } private static void waitForCondition(BooleanSupplier condition, boolean failOnTimeout, String failureMessage) throws AssertionFailedError { + waitForCondition(condition, failOnTimeout, () -> failureMessage); + } + + private static void waitForCondition(BooleanSupplier condition, boolean failOnTimeout, + Supplier failureMessageSupplier) throws AssertionFailedError { + int totalTime = 0; while (totalTime <= DEFAULT_WAIT_TIMEOUT) { @@ -423,8 +443,12 @@ public abstract class AbstractGTest { return; } - String error = failureMessage != null ? failureMessage : "Timed-out waiting for condition"; - throw new AssertionFailedError(error); + String failureMessage = "Timed-out waiting for condition"; + if (failureMessageSupplier != null) { + failureMessage = failureMessageSupplier.get(); + } + + throw new AssertionFailedError(failureMessage); } /**