mobile/android/tests/background/junit3/src/testhelpers/WaitHelper.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /* Any copyright is dedicated to the Public Domain.
     2    http://creativecommons.org/publicdomain/zero/1.0/ */
     4 package org.mozilla.gecko.background.testhelpers;
     6 import java.util.concurrent.ArrayBlockingQueue;
     7 import java.util.concurrent.BlockingQueue;
     8 import java.util.concurrent.TimeUnit;
    10 import org.mozilla.gecko.background.common.log.Logger;
    12 /**
    13  * Implements waiting for asynchronous test events.
    14  *
    15  * Call WaitHelper.getTestWaiter() to get the unique instance.
    16  *
    17  * Call performWait(runnable) to execute runnable synchronously.
    18  * runnable *must* call performNotify() on all exit paths to signal to
    19  * the TestWaiter that the runnable has completed.
    20  *
    21  * @author rnewman
    22  * @author nalexander
    23  */
    24 public class WaitHelper {
    26   public static final String LOG_TAG = "WaitHelper";
    28   public static class Result {
    29     public Throwable error;
    30     public Result() {
    31       error = null;
    32     }
    34     public Result(Throwable error) {
    35       this.error = error;
    36     }
    37   }
    39   public static abstract class WaitHelperError extends Error {
    40     private static final long serialVersionUID = 7074690961681883619L;
    41   }
    43   /**
    44    * Immutable.
    45    *
    46    * @author rnewman
    47    */
    48   public static class TimeoutError extends WaitHelperError {
    49     private static final long serialVersionUID = 8591672555848651736L;
    50     public final int waitTimeInMillis;
    52     public TimeoutError(int waitTimeInMillis) {
    53       this.waitTimeInMillis = waitTimeInMillis;
    54     }
    55   }
    57   public static class MultipleNotificationsError extends WaitHelperError {
    58     private static final long serialVersionUID = -9072736521571635495L;
    59   }
    61   public static class InterruptedError extends WaitHelperError {
    62     private static final long serialVersionUID = 8383948170038639308L;
    63   }
    65   public static class InnerError extends WaitHelperError {
    66     private static final long serialVersionUID = 3008502618576773778L;
    67     public Throwable innerError;
    69     public InnerError(Throwable e) {
    70       innerError = e;
    71       if (e != null) {
    72         // Eclipse prints the stack trace of the cause.
    73         this.initCause(e);
    74       }
    75     }
    76   }
    78   public BlockingQueue<Result> queue = new ArrayBlockingQueue<Result>(1);
    80   /**
    81    * How long performWait should wait for, in milliseconds, with the
    82    * convention that a negative value means "wait forever".
    83    */
    84   public static int defaultWaitTimeoutInMillis = -1;
    86   public void performWait(Runnable action) throws WaitHelperError {
    87     this.performWait(defaultWaitTimeoutInMillis, action);
    88   }
    90   public void performWait(int waitTimeoutInMillis, Runnable action) throws WaitHelperError {
    91     Logger.debug(LOG_TAG, "performWait called.");
    93     Result result = null;
    95     try {
    96       if (action != null) {
    97         try {
    98           action.run();
    99           Logger.debug(LOG_TAG, "Action done.");
   100         } catch (Exception ex) {
   101           Logger.debug(LOG_TAG, "Performing action threw: " + ex.getMessage());
   102           throw new InnerError(ex);
   103         }
   104       }
   106       if (waitTimeoutInMillis < 0) {
   107         result = queue.take();
   108       } else {
   109         result = queue.poll(waitTimeoutInMillis, TimeUnit.MILLISECONDS);
   110       }
   111       Logger.debug(LOG_TAG, "Got result from queue: " + result);
   112     } catch (InterruptedException e) {
   113       // We were interrupted.
   114       Logger.debug(LOG_TAG, "performNotify interrupted with InterruptedException " + e);
   115       final InterruptedError interruptedError = new InterruptedError();
   116       interruptedError.initCause(e);
   117       throw interruptedError;
   118     }
   120     if (result == null) {
   121       // We timed out.
   122       throw new TimeoutError(waitTimeoutInMillis);
   123     } else if (result.error != null) {
   124       Logger.debug(LOG_TAG, "Notified with error: " + result.error.getMessage());
   126       // Rethrow any assertion with which we were notified.
   127       InnerError innerError = new InnerError(result.error);
   128       throw innerError;
   129     }
   130     // Success!
   131   }
   133   public void performNotify(final Throwable e) {
   134     if (e != null) {
   135       Logger.debug(LOG_TAG, "performNotify called with Throwable: " + e.getMessage());
   136     } else {
   137       Logger.debug(LOG_TAG, "performNotify called.");
   138     }
   140     if (!queue.offer(new Result(e))) {
   141       // This could happen if performNotify is called multiple times (which is an error).
   142       throw new MultipleNotificationsError();
   143     }
   144   }
   146   public void performNotify() {
   147     this.performNotify(null);
   148   }
   150   public static Runnable onThreadRunnable(final Runnable r) {
   151     return new Runnable() {
   152       @Override
   153       public void run() {
   154         new Thread(r).start();
   155       }
   156     };
   157   }
   159   private static WaitHelper singleWaiter = new WaitHelper();
   160   public static WaitHelper getTestWaiter() {
   161     return singleWaiter;
   162   }
   164   public static void resetTestWaiter() {
   165     singleWaiter = new WaitHelper();
   166   }
   168   public boolean isIdle() {
   169     return queue.isEmpty();
   170   }
   171 }

mercurial