1 /*
   2  * Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 
  25 import java.lang.reflect.Method;
  26 import java.util.*;
  27 import com.sun.mirror.apt.*;
  28 
  29 
  30 /**
  31  * Annotation processor for the @Test annotation.
  32  * Invokes each method so annotated, and verifies the result.
  33  * Throws an Error on failure.
  34  *
  35  * @author Scott Seligman
  36  */
  37 public class TestProcessor implements AnnotationProcessor {
  38 
  39     AnnotationProcessorEnvironment env;
  40 
  41     // The tester that's running.
  42     Tester tester = Tester.activeTester;
  43 
  44     TestProcessor(AnnotationProcessorEnvironment env,
  45                   Tester tester) {
  46         this.env = env;
  47         this.tester = tester;
  48     }
  49 
  50 
  51     /**
  52      * Reflectively invoke the @Test-annotated methods of the live
  53      * tester.  Those methods perform the actual exercising of the
  54      * mirror API.  Then back here to verify the results by
  55      * reading the live annotations.  Convoluted, you say?
  56      */
  57     public void process() {
  58         System.out.printf("\n> Processing %s\n", tester.getClass());
  59 
  60         boolean failed = false;         // true if a test returns wrong result
  61 
  62         for (Method m : tester.getClass().getDeclaredMethods()) {
  63             Test anno = m.getAnnotation(Test.class);
  64             Ignore ignore = m.getAnnotation(Ignore.class);
  65             if (anno != null) {
  66                 if (ignore == null) {
  67                     System.out.println(">> Invoking test " + m.getName());
  68                     Object result;
  69                     try {
  70                         result = m.invoke(tester);
  71                     } catch (Exception e) {
  72                         throw new Error("Test invocation failed", e);
  73                     }
  74                     boolean ok = true;  // result of this test
  75                     if (Collection.class.isAssignableFrom(m.getReturnType())) {
  76                         ok = verifyResults((Collection) result,
  77                                            anno.result(), anno.ordered());
  78                     } else if (m.getReturnType() != void.class) {
  79                         ok = verifyResult(result, anno.result());
  80                     }
  81                     if (!ok) {
  82                         System.out.println(">>> Expected: " + anno);
  83                         System.out.println(">>> Got: " + result);
  84                         failed = true;
  85                     }
  86                 } else {
  87                     System.out.println(">> Ignoring test " + m.getName());
  88                     if (ignore.value().length() > 0) {
  89                         System.out.println(">>> Reason: " + ignore.value());
  90                     }
  91                 }
  92             }
  93         }
  94         if (failed) {
  95             throw new Error("Test(s) returned unexpected result");
  96         }
  97     }
  98 
  99     /**
 100      * Verify that a single-valued (non-Collection) result matches
 101      * its expected value.
 102      */
 103     private boolean verifyResult(Object result, String[] expected) {
 104         assert expected.length == 1 :
 105             "Single-valued test expecting " + expected.length + " results";
 106         return expected[0].equals(String.valueOf(result));
 107     }
 108 
 109     /**
 110      * Verify that a multi-valued result (a Collection) matches
 111      * its expected values.
 112      */
 113     private boolean verifyResults(Collection result,
 114                                   String[] expected, boolean ordered) {
 115         if (result.size() != expected.length) {
 116             return false;
 117         }
 118 
 119         // Convert result to an array of strings.
 120         String[] res = new String[result.size()];
 121         int i = 0;
 122         for (Object e : result) {
 123             res[i++] = String.valueOf(e);
 124         }
 125 
 126         if (!ordered) {
 127             Arrays.sort(res);
 128             Arrays.sort(expected);
 129         }
 130         return Arrays.equals(res, expected);
 131     }
 132 }