1 /*
   2  * Copyright (c) 2014, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package jdk.nashorn.internal.runtime.test;
  26 
  27 import static org.testng.Assert.fail;
  28 import java.io.ByteArrayOutputStream;
  29 import java.io.PrintStream;
  30 import java.util.regex.Matcher;
  31 import java.util.regex.Pattern;
  32 import javax.script.ScriptContext;
  33 import javax.script.ScriptEngine;
  34 import javax.script.ScriptEngineFactory;
  35 import javax.script.ScriptEngineManager;
  36 import javax.script.SimpleScriptContext;
  37 import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
  38 import org.testng.annotations.AfterTest;
  39 import org.testng.annotations.BeforeTest;
  40 import org.testng.annotations.Test;
  41 
  42 /**
  43  * @test
  44  * @bug 8037378
  45  * @summary Sanity tests for no persistence caching
  46  * @run testng/othervm jdk.nashorn.internal.runtime.test.NoPersistenceCachingTest
  47  */
  48 @SuppressWarnings("javadoc")
  49 public class NoPersistenceCachingTest {
  50 
  51    private ScriptEngine engine;
  52    private ScriptContext context1, context2, context3;
  53    private ByteArrayOutputStream stderr;
  54    private PrintStream prevStderr;
  55 
  56    @BeforeTest
  57    public void setupTest() {
  58       stderr = new ByteArrayOutputStream();
  59       prevStderr = System.err;
  60       System.setErr(new PrintStream(stderr));
  61       NashornScriptEngineFactory nashornFactory = null;
  62       final ScriptEngineManager sm = new ScriptEngineManager();
  63       for (final ScriptEngineFactory fac : sm.getEngineFactories()) {
  64          if (fac instanceof NashornScriptEngineFactory) {
  65             nashornFactory = (NashornScriptEngineFactory) fac;
  66             break;
  67          }
  68       }
  69       if (nashornFactory == null) {
  70          fail("Cannot find nashorn factory!");
  71       }
  72       // fine is enough for cache hits, finest produces way too much information
  73       // TODO this should be ported to use the RuntimeEvents instead of screen scraping
  74       // logs, as obviously this is very brittle
  75       final String[] options = new String[]{"--log=compiler:fine"};
  76       engine = nashornFactory.getScriptEngine(options);
  77       context1 = engine.getContext();
  78       context2 = new SimpleScriptContext();
  79       context2.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
  80       context3 = new SimpleScriptContext();
  81       context3.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
  82    }
  83 
  84    @AfterTest
  85    public void setErrTest() {
  86       System.setErr(prevStderr);
  87    }
  88 
  89    public void runTest(final int numberOfContext, final String expectedOutputPattern,
  90                        final int expectedPatternOccurrence) {
  91 
  92       try {
  93          switch (numberOfContext) {
  94          case 2:
  95             final String scriptTwoContexts = "print('HelloTwoContexts')";
  96             engine.eval(scriptTwoContexts, context1);
  97             engine.eval(scriptTwoContexts, context2);
  98             break;
  99          case 3:
 100             final String scriptThreeContexts = "print('HelloThreeContexts')";
 101             engine.eval(scriptThreeContexts, context1);
 102             engine.eval(scriptThreeContexts, context2);
 103             engine.eval(scriptThreeContexts, context3);
 104             break;
 105         default:
 106             break;
 107          }
 108       } catch (final Exception se) {
 109          se.printStackTrace();
 110          fail(se.getMessage());
 111       }
 112       final Pattern deoptimizing = Pattern.compile(expectedOutputPattern);
 113       final Matcher matcher = deoptimizing.matcher(stderr.toString());
 114       int matches = 0;
 115       while (matcher.find()) {
 116          matches++;
 117       }
 118       if (matches != expectedPatternOccurrence) {
 119          fail("Number of cache hit is not correct, expected: "
 120                     + expectedPatternOccurrence + " and found: " + matches + "\n"
 121               + stderr);
 122       }
 123       stderr.reset();
 124    }
 125 
 126    private static String getCodeCachePattern() {
 127       return ("\\[compiler\\]\\sCode\\scache\\shit\\sfor\\s<eval>\\savoiding\\srecompile.");
 128    }
 129 
 130     @Test
 131     public void twoContextTest() {
 132        runTest(2, getCodeCachePattern(), 1);
 133 
 134     }
 135 
 136     @Test
 137     public void threeContextTest() {
 138        runTest(3, getCodeCachePattern(), 2);
 139     }
 140 }