rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 26 Jan 2016 04:36:23 +0100
changeset 1860 4ce38f21f4cd
parent 1787 ea12a3bb4b33
child 1861 433856f897dd
permissions -rw-r--r--
JavaScript in a browser can be at most three times slower than HotSpot when computing five or ten thousands of prime numbers
     1 /**
     2  * Back 2 Browser Bytecode Translator
     3  * Copyright (C) 2012-2015 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4  *
     5  * This program is free software: you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation, version 2 of the License.
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program. Look for COPYING file in the top folder.
    16  * If not, see http://opensource.org/licenses/GPL-2.0.
    17  */
    18 package org.apidesign.bck2brwsr.vmtest.impl;
    19 
    20 import java.lang.annotation.Annotation;
    21 import org.apidesign.bck2brwsr.vmtest.*;
    22 import java.lang.reflect.Method;
    23 import java.util.ArrayList;
    24 import java.util.List;
    25 import org.apidesign.bck2brwsr.launcher.Launcher;
    26 import org.testng.Assert;
    27 import org.testng.ITest;
    28 import org.testng.annotations.Factory;
    29 import org.testng.annotations.Test;
    30 
    31 /** A TestNG {@link Factory} that seeks for {@link Compare} annotations
    32  * in provided class and builds set of tests that compare the computations
    33  * in real as well as JavaScript virtual machines. Use as:<pre>
    34  * {@code @}{@link Factory} public static create() {
    35  *   return @{link VMTest}.{@link #create(YourClass.class);
    36  * }</pre>
    37  *
    38  * @author Jaroslav Tulach <jtulach@netbeans.org>
    39  */
    40 public final class CompareCase implements ITest {
    41     private final Bck2BrwsrCase first, second;
    42     private final Method m;
    43     private final double slowdown;
    44     
    45     private CompareCase(Method m, Bck2BrwsrCase first, Bck2BrwsrCase second, double slowdown) {
    46         this.first = first;
    47         this.second = second;
    48         this.m = m;
    49         this.slowdown = slowdown;
    50     }
    51 
    52     /** Inspects <code>clazz</code> and for each {@lik Compare} method creates
    53      * instances of tests. Each instance runs the test in different virtual
    54      * machine and at the end they compare the results.
    55      * 
    56      * @param clazz the class to inspect
    57      * @return the set of created tests
    58      */
    59     public static Object[] create(String[] brwsr, Class[] classes, Class<? extends Annotation> brwsrTest) {
    60         List<Object> ret = new ArrayList<>();
    61         
    62         final LaunchSetup l = LaunchSetup.INSTANCE;
    63         ret.add(l);
    64         
    65         {
    66             String p = System.getProperty("vmtest.brwsrs");
    67             if (p != null) {
    68                 brwsr = p.split(",");
    69             }
    70         }
    71         
    72         for (Class clazz : classes) {
    73             Method[] arr = clazz.getMethods();
    74             for (Method m : arr) {
    75                 registerCompareCases(m, l, ret, brwsr);
    76                 registerBrwsrCases(brwsrTest, m, l, ret, brwsr);
    77             }
    78         }
    79         return ret.toArray();
    80     }
    81 
    82     /** Test that compares the previous results.
    83      * @throws Throwable 
    84      */
    85     @Test(dependsOnGroups = "run") public void compareResults() throws Throwable {
    86         Object v1 = first.value;
    87         Object v2 = second.value;
    88         if (v1 instanceof Integer || v1 instanceof Long || v1 instanceof Byte || v1 instanceof Short) {
    89             try {
    90                 v1 = Long.parseLong(v1.toString());
    91             } catch (NumberFormatException nfe) {
    92                 v1 = "Can't parse " + v1.toString();
    93             }
    94             try {
    95                 v2 = Long.parseLong(v2.toString());
    96             } catch (NumberFormatException nfe) {
    97                 v2 = "Can't parse " + v2.toString();
    98             }
    99         } else if (v1 instanceof Number) {
   100             try {
   101                 v1 = Double.parseDouble(v1.toString());
   102             } catch (NumberFormatException nfe) {
   103                 v1 = "Can't parse " + v1.toString();
   104             }
   105             try {
   106                 v2 = Double.parseDouble(v2.toString());
   107             } catch (NumberFormatException nfe) {
   108                 v2 = "Can't parse " + v2.toString();
   109             }
   110         } else {
   111             if (v1 != null) {
   112                 v1 = v1.toString();
   113             } else {
   114                 v1 = "null";
   115             }
   116         }
   117         try {
   118             Assert.assertEquals(v2, v1, "Comparing results");
   119         } catch (AssertionError e) {
   120             StringBuilder sb = new StringBuilder();
   121             sb.append(e.getMessage());
   122             Bck2BrwsrCase.dumpJS(sb, second);
   123             throw new AssertionError(sb.toString());
   124         }
   125         if (slowdown > 0.0) {
   126             Bck2BrwsrCase slow;
   127             Bck2BrwsrCase fast;
   128             if (first.time >= second.time) {
   129                 slow = second;
   130                 fast = first;
   131             } else {
   132                 fast = second;
   133                 slow = first;
   134             }
   135             if (slow.time * slowdown < fast.time) {
   136                 Assert.fail("Too slow " + slow.getTestName() + " took " + slow.time + " ms vs. " + fast.time + " ms of " + fast.getTestName());
   137             }
   138         }
   139     }
   140     
   141     /** Test name.
   142      * @return name of the tested method followed by a suffix
   143      */
   144     @Override
   145     public String getTestName() {
   146         return m.getName() + "[Compare " + second.typeName() + "]";
   147     }
   148     
   149     private static void registerCompareCases(Method m, final LaunchSetup l, List<Object> ret, String[] brwsr) {
   150         Compare c = m.getAnnotation(Compare.class);
   151         if (c == null) {
   152             return;
   153         }
   154         String slowdownOverride = System.getProperty("vmtest.slowdown");
   155         final Bck2BrwsrCase real = new Bck2BrwsrCase(m, "Java", null, false, null, null);
   156         ret.add(real);
   157         double slowdown = c.slowdown();
   158         if (slowdown > 0.0 && slowdownOverride != null) {
   159             slowdown = Double.parseDouble(slowdownOverride);
   160         }
   161         if (c.scripting()) {
   162             final Bck2BrwsrCase js = new Bck2BrwsrCase(m, "JavaScript", l.javaScript(), false, null, null);
   163             ret.add(js);
   164             ret.add(new CompareCase(m, real, js, slowdown));
   165         }
   166         for (String b : brwsr) {
   167             final Launcher s = l.brwsr(b);
   168             ret.add(s);
   169             final Bck2BrwsrCase cse = new Bck2BrwsrCase(m, b, s, false, null, null);
   170             ret.add(cse);
   171             ret.add(new CompareCase(m, real, cse, slowdown));
   172         }
   173     }
   174     private static void registerBrwsrCases(Class<? extends Annotation> brwsrTest, Method m, final LaunchSetup l, List<Object> ret, String[] brwsr) {
   175         Object c = m.getAnnotation(brwsrTest);
   176         if (c == null) {
   177             return;
   178         }
   179         HtmlFragment f = m.getAnnotation(HtmlFragment.class);
   180         if (f == null) {
   181             f = m.getDeclaringClass().getAnnotation(HtmlFragment.class);
   182         }
   183         Http.Resource[] r = {};
   184         Http h = m.getAnnotation(Http.class);
   185         if (h == null) {
   186             h = m.getDeclaringClass().getAnnotation(Http.class);
   187             if (h != null) {
   188                 r = h.value();
   189             }
   190         } else {
   191             r = h.value();
   192         }
   193         if (brwsr.length == 0) {
   194             final Launcher s = l.brwsr(null);
   195             ret.add(s);
   196             ret.add(new Bck2BrwsrCase(m, "Brwsr", s, true, f, r));
   197         } else {
   198             for (String b : brwsr) {
   199                 final Launcher s = l.brwsr(b);
   200                 ret.add(s);
   201                 ret.add(new Bck2BrwsrCase(m, b, s, true, f, r));
   202             }
   203         }
   204     }
   205 }