summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authormkosiba@chromium.org <mkosiba@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-15 15:46:34 +0000
committermkosiba@chromium.org <mkosiba@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-15 15:46:34 +0000
commit20855f88ab2c1057a67f5ea119708df853dc335a (patch)
treef1021bf5fe373ac8a422f284e318269a78d3e788 /content
parent3d218815b543d1ee8229273678971581c9dc592d (diff)
downloadchromium_src-20855f88ab2c1057a67f5ea119708df853dc335a.zip
chromium_src-20855f88ab2c1057a67f5ea119708df853dc335a.tar.gz
chromium_src-20855f88ab2c1057a67f5ea119708df853dc335a.tar.bz2
[android] Improve CallbackHelper documentation.
After spending way too much time explaining the use of this class (crrev.com/12652003) I thought that improving the docs would be a good idea. Also, making mCallCount private as subclasses shouldn't read the value without synchronizing on the lock. BUG=None TEST=Builds NOTRY=True Review URL: https://chromiumcodereview.appspot.com/12645009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@188394 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/public/test/android/javatests/src/org/chromium/content/browser/test/util/CallbackHelper.java114
1 files changed, 112 insertions, 2 deletions
diff --git a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/CallbackHelper.java b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/CallbackHelper.java
index 95646e2..f2e9a292 100644
--- a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/CallbackHelper.java
+++ b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/CallbackHelper.java
@@ -8,13 +8,123 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
- * A helper class for listening to callbacks.
+ * A helper class that encapsulates listening and blocking for callbacks.
+ *
+ * Sample usage:
+ *
+ * // Let us assume that this interface is defined by some piece of production code and is used
+ * // to communicate events that occur in that piece of code. Let us further assume that the
+ * // production code runs on the main thread test code runs on a separate test thread.
+ * // An instance that implements this interface would be injected by test code to ensure that the
+ * // methods are being called on another thread.
+ * interface Delegate {
+ * void onOperationFailed(String errorMessage);
+ * void onDataPersisted();
+ * }
+ *
+ * // This is the inner class you'd write in your test case to later inject into the production
+ * // code.
+ * class TestDelegate implements Delegate {
+ * // This is the preferred way to create a helper that stores the parameters it receives
+ * // when called by production code.
+ * public static class OnOperationFailedHelper extends CallbackHelper {
+ * private String mErrorMessage;
+ *
+ * public void getErrorMessage() {
+ * assert getCallCount() > 0;
+ * return mErrorMessage;
+ * }
+ *
+ * public void notifyCalled(String errorMessage) {
+ * mErrorMessage = errorMessage;
+ * // It's important to call this after all parameter assignments.
+ * notifyCalled();
+ * }
+ * }
+ *
+ * // There should be one CallbackHelper instance per method.
+ * private OnOperationFailedHelper mOnOperationFailedHelper;
+ * private CallbackHelper mOnDataPersistedHelper;
+ *
+ * public OnOperationFailedHelper getOnOperationFailedHelper() {
+ * return mOnOperationFailedHelper;
+ * }
+ *
+ * public CallbackHelper getOnDataPersistedHelper() {
+ * return mOnDataPersistedHelper;
+ * }
+ *
+ * @Override
+ * public void onOperationFailed(String errorMessage) {
+ * mOnOperationFailedHelper.notifyCalled(errorMessage);
+ * }
+ *
+ * @Override
+ * public void onDataPersisted() {
+ * mOnDataPersistedHelper.notifyCalled();
+ * }
+ * }
+ *
+ * // This is a sample test case.
+ * public void testCase() throws Exception {
+ * // Create the TestDelegate to inject into production code.
+ * TestDelegate delegate = new TestDelegate();
+ * // Create the production class instance that is being tested and inject the test delegate.
+ * CodeUnderTest codeUnderTest = new CodeUnderTest();
+ * codeUnderTest.setDelegate(delegate);
+ *
+ * // Typically you'd get the current call count before performing the operation you expect to
+ * // trigger the callback. There can't be any callbacks 'in flight' at this moment, otherwise
+ * // the call count is unpredictable and the test will be flaky.
+ * int onOperationFailedCallCount = delegate.getOnOperationFailedHelper().getCallCount();
+ * codeUnderTest.doSomethingThatEndsUpCallingOnOperationFailedFromAnotherThread();
+ * // It's safe to do other stuff here, if needed.
+ * ....
+ * // Wait for the callback if it hadn't been called yet, otherwise return immediately. This
+ * // can throw an exception if the callback doesn't arrive within the timeout.
+ * delegate.getOnOperationFailedHelper().waitForCallback(onOperationFailedCallCount);
+ * // Access to method parameters is now safe.
+ * assertEquals("server error", delegate.getOnOperationFailedHelper().getErrorMessage());
+ *
+ * // Being able to pass the helper around lets us build methods which encapsulate commonly
+ * // performed tasks.
+ * doSomeOperationAndWait(codeUnerTest, delegate.getOnOperationFailedHelper());
+ *
+ * // The helper can be resued for as many calls as needed, just be sure to get the count each
+ * // time.
+ * onOperationFailedCallCount = delegate.getOnOperationFailedHelper().getCallCount();
+ * codeUnderTest.doSomethingElseButStillFailOnAnotherThread();
+ * delegate.getOnOperationFailedHelper().waitForCallback(onOperationFailedCallCount);
+ *
+ * // It is also possible to use more than one helper at a time.
+ * onOperationFailedCallCount = delegate.getOnOperationFailedHelper().getCallCount();
+ * int onDataPersistedCallCount = delegate.getOnDataPersistedHelper().getCallCount();
+ * codeUnderTest.doSomethingThatPersistsDataButFailsInSomeOtherWayOnAnotherThread();
+ * delegate.getOnDataPersistedHelper().waitForCallback(onDataPersistedCallCount);
+ * delegate.getOnOperationFailedHelper().waitForCallback(onOperationFailedCallCount);
+ * }
+ *
+ * // Shows how to turn an async operation + completion callback into a synchronous operation.
+ * private void doSomeOperationAndWait(final CodeUnderTest underTest,
+ * CallbackHelper operationHelper) throws InterruptedException, TimeoutException {
+ * final int callCount = operaitonHelper.getCallCount();
+ * getInstrumentaiton().runOnMainSync(new Runnable() {
+ * @Override
+ * public void run() {
+ * // This schedules a call to a method on the injected TestDelegate. The TestDelegate
+ * // implementation will then call operationHelper.notifyCalled().
+ * underTest.operation();
+ * }
+ * });
+ * operationHelper.waitForCallback(callCount);
+ * }
+ *
*/
public class CallbackHelper {
protected static int WAIT_TIMEOUT_SECONDS = 5;
private final Object mLock = new Object();
- protected int mCallCount = 0;
+ private int mCallCount = 0;
/**
* Gets the number of times the callback has been called.