Home | History | Annotate | Download | only in testng
      1 package org.testng;
      2 
      3 import java.io.PrintStream;
      4 import java.io.PrintWriter;
      5 import java.text.DateFormat;
      6 import java.text.ParseException;
      7 import java.text.SimpleDateFormat;
      8 import java.util.Calendar;
      9 import java.util.Date;
     10 
     11 /**
     12  * A {@link SkipException} extension that transforms a skipped method
     13  * into a failed method based on a time trigger.
     14  * <p/>
     15  * By default the time format is yyyy/MM/dd (according to {@code SimpleDateFormat}).
     16  * You can customize this by using the specialized constructors. Suppported date
     17  * formats are according to the {@code SimpleDateFormat}.
     18  *
     19  * @author <a href='mailto:the[dot]mindstorm[at]gmail[dot]com'>Alex Popescu</a>
     20  * @since 5.6
     21  */
     22 public class TimeBombSkipException extends SkipException {
     23   private static final long serialVersionUID = -8599821478834048537L;
     24   private static final SimpleDateFormat SDF= new SimpleDateFormat("yyyy/MM/dd");
     25   private Calendar m_expireDate;
     26   private DateFormat m_inFormat= SDF;
     27   private DateFormat m_outFormat= SDF;
     28 
     29   /**
     30    * Creates a {@code TimeBombedSkipException} using the <tt>expirationDate</tt>.
     31    * The format used for date comparison is <tt>yyyy/MM/dd</tt>
     32    * @param msg exception message
     33    * @param expirationDate time limit after which the SKIP becomes a FAILURE
     34    */
     35   public TimeBombSkipException(String msg, Date expirationDate) {
     36     super(msg);
     37     initExpireDate(expirationDate);
     38   }
     39 
     40   /**
     41    * Creates a {@code TimeBombedSkipException} using the <tt>expirationDate</tt>.
     42    * The <tt>format</tt> parameter wiil be used for performing the time comparison.
     43    * @param msg exception message
     44    * @param expirationDate time limit after which the SKIP becomes a FAILURE
     45    * @param format format for the time comparison
     46    */
     47   public TimeBombSkipException(String msg, Date expirationDate, String format) {
     48     super(msg);
     49     m_inFormat= new SimpleDateFormat(format);
     50     m_outFormat= new SimpleDateFormat(format);
     51     initExpireDate(expirationDate);
     52   }
     53 
     54   /**
     55    * Creates a {@code TimeBombedSkipException} using the <tt>date</tt>
     56    * in the format <tt>yyyy/MM/dd</tt>.
     57    * @param msg exception message
     58    * @param date time limit after which the SKIP becomes a FAILURE
     59    */
     60   public TimeBombSkipException(String msg, String date) {
     61     super(msg);
     62     initExpireDate(date);
     63   }
     64 
     65   /**
     66    * Creates a {@code TimeBombedSkipException} using the <tt>date</tt>
     67    * in the specified format <tt>format</tt>. The same format is used
     68    * when performing the time comparison.
     69    * @param msg exception message
     70    * @param date time limit after which the SKIP becomes a FAILURE
     71    * @param format format of the passed in <tt>date</tt> and of the time comparison
     72    */
     73   public TimeBombSkipException(String msg, String date, String format) {
     74     this(msg, date, format, format);
     75   }
     76 
     77   /**
     78    * Creates a {@code TimeBombedSkipException} using the <tt>date</tt>
     79    * in the specified format <tt>inFormat</tt>. The <tt>outFormat</tt> will be
     80    * used to perform the time comparison and display.
     81    * @param msg exception message
     82    * @param date time limit after which the SKIP becomes a FAILURE
     83    * @param inFormat format of the passed in <tt>date</tt>
     84    * @param outFormat format of the time comparison
     85    */
     86   public TimeBombSkipException(String msg, String date, String inFormat, String outFormat) {
     87     super(msg);
     88     m_inFormat= new SimpleDateFormat(inFormat);
     89     m_outFormat= new SimpleDateFormat(outFormat);
     90     initExpireDate(date);
     91   }
     92 
     93   /**
     94    * Creates a {@code TimeBombedSkipException} using the <tt>expirationDate</tt>.
     95    * The format used for date comparison is <tt>yyyy/MM/dd</tt>
     96    * @param msg exception message
     97    * @param expirationDate time limit after which the SKIP becomes a FAILURE
     98    * @param cause the cause (which is saved for later retrieval by the
     99    *         {@link #getCause()} method).  (A <tt>null</tt> value is
    100    *         permitted, and indicates that the cause is nonexistent or
    101    *         unknown.)
    102    */
    103   public TimeBombSkipException(String msg, Date expirationDate, Throwable cause) {
    104     super(msg, cause);
    105     initExpireDate(expirationDate);
    106   }
    107 
    108   /**
    109    * Creates a {@code TimeBombedSkipException} using the <tt>expirationDate</tt>.
    110    * The <tt>format</tt> parameter wiil be used for performing the time comparison.
    111    * @param msg exception message
    112    * @param expirationDate time limit after which the SKIP becomes a FAILURE
    113    * @param format format for the time comparison
    114    * @param cause the cause (which is saved for later retrieval by the
    115    *         {@link #getCause()} method).  (A <tt>null</tt> value is
    116    *         permitted, and indicates that the cause is nonexistent or
    117    *         unknown.)
    118    */
    119   public TimeBombSkipException(String msg, Date expirationDate, String format, Throwable cause) {
    120     super(msg, cause);
    121     m_inFormat= new SimpleDateFormat(format);
    122     m_outFormat= new SimpleDateFormat(format);
    123     initExpireDate(expirationDate);
    124   }
    125 
    126   /**
    127    * Creates a {@code TimeBombedSkipException} using the <tt>date</tt>
    128    * in the format <tt>yyyy/MM/dd</tt>.
    129    * @param msg exception message
    130    * @param date time limit after which the SKIP becomes a FAILURE
    131    * @param cause the cause (which is saved for later retrieval by the
    132    *         {@link #getCause()} method).  (A <tt>null</tt> value is
    133    *         permitted, and indicates that the cause is nonexistent or
    134    *         unknown.)
    135    */
    136   public TimeBombSkipException(String msg, String date, Throwable cause) {
    137     super(msg, cause);
    138     initExpireDate(date);
    139   }
    140 
    141   /**
    142    * Creates a {@code TimeBombedSkipException} using the <tt>date</tt>
    143    * in the specified format <tt>format</tt>. The same format is used
    144    * when performing the time comparison.
    145    * @param msg exception message
    146    * @param date time limit after which the SKIP becomes a FAILURE
    147    * @param format format of the passed in <tt>date</tt> and of the time comparison
    148    * @param cause the cause (which is saved for later retrieval by the
    149    *         {@link #getCause()} method).  (A <tt>null</tt> value is
    150    *         permitted, and indicates that the cause is nonexistent or
    151    *         unknown.)
    152    */
    153   public TimeBombSkipException(String msg, String date, String format, Throwable cause) {
    154     this(msg, date, format, format, cause);
    155   }
    156 
    157   /**
    158    * Creates a {@code TimeBombedSkipException} using the <tt>date</tt>
    159    * in the specified format <tt>inFormat</tt>. The <tt>outFormat</tt> will be
    160    * used to perform the time comparison and display.
    161    * @param msg exception message
    162    * @param date time limit after which the SKIP becomes a FAILURE
    163    * @param inFormat format of the passed in <tt>date</tt>
    164    * @param outFormat format of the time comparison
    165    * @param cause the cause (which is saved for later retrieval by the
    166    *         {@link #getCause()} method).  (A <tt>null</tt> value is
    167    *         permitted, and indicates that the cause is nonexistent or
    168    *         unknown.)
    169    */
    170   public TimeBombSkipException(String msg, String date, String inFormat, String outFormat, Throwable cause) {
    171     super(msg, cause);
    172     m_inFormat= new SimpleDateFormat(inFormat);
    173     m_outFormat= new SimpleDateFormat(outFormat);
    174     initExpireDate(date);
    175   }
    176 
    177   private void initExpireDate(Date expireDate) {
    178     m_expireDate= Calendar.getInstance();
    179     m_expireDate.setTime(expireDate);
    180   }
    181 
    182   private void initExpireDate(String date) {
    183     try {
    184       // SimpleDateFormat is not thread-safe, and m_inFormat
    185       // is, by default, connected to the static SDF variable
    186       synchronized( m_inFormat ){
    187         Date d = m_inFormat.parse(date);
    188         initExpireDate(d);
    189       }
    190     }
    191     catch(ParseException pex) {
    192       throw new TestNGException("Cannot parse date:" + date + " using pattern: " + m_inFormat, pex);
    193     }
    194   }
    195 
    196   @Override
    197   public boolean isSkip() {
    198     if (null == m_expireDate) {
    199       return false;
    200     }
    201 
    202     try {
    203       Calendar now= Calendar.getInstance();
    204       Date nowDate= m_inFormat.parse(m_inFormat.format(now.getTime()));
    205       now.setTime(nowDate);
    206 
    207       return !now.after(m_expireDate);
    208     }
    209     catch(ParseException pex) {
    210       throw new TestNGException("Cannot compare dates.");
    211     }
    212   }
    213 
    214   @Override
    215   public String getMessage() {
    216     if(isSkip()) {
    217       return super.getMessage();
    218     }
    219     else {
    220       return super.getMessage() + "; Test must have been enabled by: " + m_outFormat.format(m_expireDate.getTime());
    221     }
    222   }
    223 
    224   @Override
    225   public void printStackTrace(PrintStream s) {
    226     reduceStackTrace();
    227     super.printStackTrace(s);
    228   }
    229 
    230   @Override
    231   public void printStackTrace(PrintWriter s) {
    232     reduceStackTrace();
    233     super.printStackTrace(s);
    234   }
    235 }
    236