1 /*
   2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 package org.apache.qetest.xsl;
  21 
  22 import org.apache.qetest.CheckingHandler;
  23 import static org.apache.qetest.CheckingHandler.Expectation.ITEM_CHECKPASS;
  24 import static org.apache.qetest.CheckingHandler.Expectation.ITEM_DONT_CARE;
  25 import static org.testng.Assert.fail;
  26 import org.xml.sax.ErrorHandler;
  27 import org.xml.sax.SAXException;
  28 import org.xml.sax.SAXParseException;
  29 
  30 /**
  31  * Cheap-o ErrorHandler for use by API tests.
  32  */
  33 public class CheckingSAXErrorHandler implements CheckingHandler, ErrorHandler {
  34 
  35     /**
  36      * Constants determining when we should throw exceptions.
  37      * <ul>Flags are combineable like a bitfield.
  38      * <li>THROW_NEVER - never ever (always continue - note this may have
  39      * unexpected effects when fatalErrors happen, see
  40      * {@link javax.xml.transform.ErrorListener#fatalError(javax.xml.transform.TransformerException)}</li>
  41      * <li>THROW_ON_WARNING - throw only on warnings</li>
  42      * <li>THROW_ON_ERROR - throw only on errors</li>
  43      * <li>THROW_ON_FATAL - throw only on fatalErrors - default</li>
  44      * <li>THROW_ALWAYS - always throw exceptions</li>
  45      * </ul>
  46      */
  47     public static final int THROW_NEVER = 0;
  48 
  49     /**
  50      * THROW_ON_WARNING - throw only on warnings.
  51      */
  52     public static final int THROW_ON_WARNING = 1;
  53 
  54     /**
  55      * THROW_ON_ERROR - throw only on errors.
  56      */
  57     public static final int THROW_ON_ERROR = 2;
  58 
  59     /**
  60      * THROW_ON_FATAL - throw only on fatalErrors - default.
  61      */
  62     public static final int THROW_ON_FATAL = 4;
  63 
  64     /**
  65      * THROW_ALWAYS - always throw exceptions.
  66      */
  67     public static final int THROW_ALWAYS = THROW_ON_WARNING | THROW_ON_ERROR
  68             | THROW_ON_FATAL;
  69 
  70     /**
  71      * If we should throw an exception for each message type.
  72      */
  73     private final int throwWhen;
  74 
  75     /**
  76      * Constructor set when we should re-throw exceptions.
  77      *
  78      * @param t THROW_WHEN_* constant as to when we should re-throw an exception
  79      * when we are called
  80      */
  81     public CheckingSAXErrorHandler(int t) {
  82         throwWhen = t;
  83     }
  84 
  85     /**
  86      * Default constructor will behave as default. Throw only when there is 
  87      * non-recoverable error.
  88      */ 
  89     public CheckingSAXErrorHandler() {
  90         this.throwWhen = THROW_ON_FATAL;
  91     }
  92 
  93     /**
  94      * Tells us when we should re-throw exceptions.
  95      *
  96      * @return THROW_WHEN_* constant as to when we should re-throw an exception
  97      * when we are called
  98      */
  99     public int getThrowWhen() {
 100         return throwWhen;
 101     }
 102 
 103     /**
 104      * Constant for items returned in getCounters: messages.
 105      */
 106     public static final int TYPE_WARNING = 0;
 107 
 108     /**
 109      * Constant for items returned in getCounters: errors.
 110      */
 111     public static final int TYPE_ERROR = 1;
 112 
 113     /**
 114      * Constant for items returned in getCounters: fatalErrors.
 115      */
 116     public static final int TYPE_FATALERROR = 2;
 117 
 118     /**
 119      * Expected values for events we may handle, default=ITEM_DONT_CARE.
 120      */
 121     private final Expectation[] expected = {
 122         ITEM_DONT_CARE, /* warning */
 123         ITEM_DONT_CARE, /* error */
 124         ITEM_DONT_CARE /* fatalError */};
 125 
 126     /**
 127      * Ask us to report checkPass/Fail for certain events we handle. Since we
 128      * may have to handle many events between when a test will be able to call
 129      * us, testers can set this to have us automatically call checkPass when we
 130      * see an item that matches, or to call checkFail when we get an unexpected
 131      * item. Generally, we only call check* methods when:
 132      * <ul>
 133      * <li>containsString is not set, reset, or is ITEM_DONT_CARE, we do nothing
 134      * (i.e. never call check* for this item)</li>
 135      * <li>containsString is ITEM_CHECKFAIL, we will always call checkFail with
 136      * the contents of any item if it occurs</li>
 137      * <li>containsString is anything else, we will grab a String representation
 138      * of every item of that type that comes along, and if the containsString is
 139      * found, case-sensitive, within the handled item's string, call checkPass,
 140      * otherwise call checkFail</li>
 141      * </ul>
 142      * Note that any time we handle a particular event that was expected, we
 143      * un-set the expected value for that item. This means that you can only ask
 144      * us to validate one occurrence of any particular event; all events after
 145      * that one will be treated as ITEM_DONT_CARE. Callers can of course call
 146      * setExpected again, of course, but this covers the case where we handle
 147      * multiple events in a single block, perhaps out of the caller's direct
 148      * control. Note that we first store the event via setLast(), then we
 149      * validate the event as above, and then we potentially re-throw the
 150      * exception as by setThrowWhen().
 151      *
 152      * @param itemType which of the various types of items we might handle;
 153      * should be defined as a constant by subclasses
 154      * @param expectation expectation if we need check or not.
 155      */
 156     @Override
 157     public void setExpected(int itemType, Expectation expectation) {
 158         expected[itemType] = expectation;
 159     }
 160 
 161     /**
 162      * Reset all items or counters we've handled.
 163      */
 164     @Override
 165     public void reset() {
 166         for (int j = 0; j < expected.length; j++) {
 167             expected[j] = ITEM_DONT_CARE;
 168         }
 169     }
 170 
 171     /**
 172      * Receive notification of a warning. fail the test if it expects pass.
 173      * Re-throw the exception when re-throw flag is set.
 174      * @param exception The error information encapsulated in a
 175      *                  SAX parse exception.
 176      * @exception org.xml.sax.SAXException Any SAX exception, possibly
 177      *            wrapping another exception. 
 178      */
 179     @Override
 180     public void warning(SAXParseException exception) throws SAXException {
 181         // Log or validate the exception
 182         if (expected[TYPE_WARNING] == ITEM_CHECKPASS) {
 183             fail("Unexpected error: ex " + exception);
 184         }
 185 
 186         // Also re-throw the exception if asked to
 187         if ((throwWhen & THROW_ON_WARNING) == THROW_ON_WARNING) {
 188             // Note: re-throw the SAME exception, not a new one!
 189             throw exception;
 190         }
 191     }
 192 
 193     /**
 194      * Receive notification of a recoverable error. fail the test if it expects
 195      * pass. Re-throw the exception when re-throw flag is set.
 196      * @param exception The error information encapsulated in a
 197      *                  SAX parse exception.
 198      * @exception org.xml.sax.SAXException Any SAX exception, possibly
 199      *            wrapping another exception. 
 200      */
 201     @Override
 202     public void error(SAXParseException exception) throws SAXException {
 203         // validate the exception
 204         if (expected[TYPE_FATALERROR] == ITEM_CHECKPASS) {
 205             fail("Unexpected fatal error: ex " + exception);
 206         }
 207 
 208         // Also re-throw the exception if asked to
 209         if ((throwWhen & THROW_ON_ERROR) == THROW_ON_ERROR) {
 210             // Note: re-throw the SAME exception, not a new one!
 211             throw exception;
 212         }
 213     }
 214 
 215     /**
 216      * Receive notification of a non-recoverable error. fail the test if it 
 217      * expects pass. Re-throw the exception when re-throw flag is set.
 218      * @param exception The error information encapsulated in a
 219      *                  SAX parse exception.
 220      * @exception org.xml.sax.SAXException Any SAX exception, possibly
 221      *            wrapping another exception. 
 222      */
 223     @Override
 224     public void fatalError(SAXParseException exception) throws SAXException {
 225         // validate the exception
 226         if (expected[TYPE_ERROR] == ITEM_CHECKPASS) {
 227             fail("Unexpected fatal error: ex " + exception);
 228         }
 229 
 230         // Also re-throw the exception if asked to
 231         if ((throwWhen & THROW_ON_FATAL) == THROW_ON_FATAL) {
 232             // Note: re-throw the SAME exception, not a new one!
 233             throw exception;
 234         }
 235     }
 236 }