/*
* (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* Thierry Delprat <tdelprat@nuxeo.com>
*/
package org.nuxeo.automation.scripting.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptContext;
import org.apache.commons.io.IOUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.nuxeo.automation.scripting.AutomationScriptingFeature;
import org.nuxeo.automation.scripting.api.AutomationScriptingService;
import org.nuxeo.automation.scripting.internals.ScriptObjectMirrors;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.runtime.test.runner.Features;
import org.nuxeo.runtime.test.runner.FeaturesRunner;
import com.google.common.base.Charsets;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
/**
* @since 7.2
*/
@RunWith(FeaturesRunner.class)
@Features(AutomationScriptingFeature.class)
public class TestCompileAndContext {
@Inject
CoreSession session;
@Inject
AutomationScriptingService pool;
ByteArrayOutputStream outContent = new ByteArrayOutputStream();
private PrintStream outStream;
@Before
public void setUpStreams() {
outStream = System.out;
System.setOut(new PrintStream(outContent));
}
@After
public void cleanUpStreams() throws IOException {
outContent.close();
System.setOut(outStream);
}
@Test
public void serviceShouldBeDeclared() throws Exception {
try (AutomationScriptingService.Session ref = pool.get(session)) {
try (InputStream stream = this.getClass().getResourceAsStream("/checkWrapper.js")) {
assertNotNull(stream);
ref.run(stream);
}
}
}
@Test
public void testNashornWithCompile() throws Exception {
try (AutomationScriptingService.Session ref = pool.get(session)) {
Compilable compiler = ref.adapt(Compilable.class);
assertNotNull(compiler);
try (InputStream stream = this.getClass().getResourceAsStream("/testScript.js")) {
assertNotNull(stream);
String js = IOUtils.toString(stream);
CompiledScript compiled = compiler.compile(new StringReader(js));
final ScriptContext context = ref.adapt(ScriptContext.class);
ByteArrayOutputStream output = new ByteArrayOutputStream();
context.setWriter(new OutputStreamWriter(output));
context.setAttribute("mapper", new Mapper(context), ScriptContext.ENGINE_SCOPE);
compiled.eval(context);
assertEquals(
"1" + System.lineSeparator() + "str" + System.lineSeparator() + "[1, 2, {a=1, b=2}]"
+ System.lineSeparator() + "{a=1, b=2}" + System.lineSeparator() + "This is a string"
+ System.lineSeparator() + "This is a string" + System.lineSeparator() + "2"
+ System.lineSeparator() + "[A, B, C]" + System.lineSeparator()
+ "{a=salut, b=from java}" + System.lineSeparator() + "done" + System.lineSeparator(),
output.toString());
}
}
}
@Ignore("for performance testing purpose")
@Test
public void testPerf() throws Exception {
long start = System.currentTimeMillis();
for (int i = 0; i < 500; i++) {
try (AutomationScriptingService.Session ref = pool.get(session)) {
;
}
}
long end = System.currentTimeMillis();
System.err.println("DEBUG: Logic A toke " + (end - start) + " " + "MilliSeconds");
}
protected InputStream getScriptWithRandomContent(String content) {
// change the content of the script !
return new ByteArrayInputStream(("var t=" + System.currentTimeMillis() + content).getBytes(Charsets.UTF_8));
}
@Ignore("for performance testing purpose")
@Test
public void checkScriptingEngineCostAndIsolation() throws Exception {
try (AutomationScriptingService.Session session = pool.get(this.session)) {
try (InputStream stream = this.getClass().getResourceAsStream("/QuickScript.js")) {
assertNotNull(stream);
String js = IOUtils.toString(stream);
// long t0 = System.currentTimeMillis();
session.run(getScriptWithRandomContent(js));
// long t1 = System.currentTimeMillis();
// System.err.println("Initial Exec = " + (t1-t0));
// t0 = System.currentTimeMillis();
session.run(getScriptWithRandomContent(js));
// t1 = System.currentTimeMillis();
// System.err.println("Second Exec = " + (t1-t0));
int nbIter = 50;
// long t = t1 - t0;
for (int i = 0; i < nbIter; i++) {
// t0 = System.currentTimeMillis();
session.run(getScriptWithRandomContent(js));
// t1 = System.currentTimeMillis();
// System.err.println("Exec = " + (t1-t0));
// t += t1 - t0;
}
// System.err.println("AvgExec = " + (t/(nbIter + 1.0)));
// now we check isolation
session.run(this.getClass().getResourceAsStream("/checkIsolation.js"));
session.run(this.getClass().getResourceAsStream("/checkIsolation.js"));
session.run(new ByteArrayInputStream("Document.Fetch=\"toto\";".getBytes(Charsets.UTF_8)));
session.run(this.getClass().getResourceAsStream("/checkIsolation.js"));
}
}
}
public class Mapper {
final PrintWriter out;
Mapper(ScriptContext context) {
out = new PrintWriter(context.getWriter());
}
final public Object callMe(ScriptObjectMirror params) throws IOException {
@SuppressWarnings("unchecked")
Map<String, Object> map = (Map<String, Object>) ScriptObjectMirrors.unwrap(params);
Integer p1 = (Integer) map.get("p1");
String p2 = (String) map.get("p2");
@SuppressWarnings("unchecked")
List<Object> p3 = (List<Object>) map.get("p3");
assertEquals(3, p3.size());
@SuppressWarnings("unchecked")
Map<String, Object> nested = (Map<String, Object>) p3.get(2);
out.println(p1);
out.println(p2);
out.println(p3);
out.println(nested);
Map<String, Object> data = new HashMap<>();
data.put("p1", "This is a string");
data.put("p2", 2);
List<String> l = new ArrayList<String>();
l.add("A");
l.add("B");
l.add("C");
data.put("p3", l);
Map<String, Object> nested2 = new HashMap<>();
nested2.put("a", "salut");
nested2.put("b", "from java");
data.put("p4", nested2);
return ScriptObjectMirrors.wrap(data);
}
}
@Test
public void testIsolationScriptCtx() throws Exception {
try (AutomationScriptingService.Session scripting1 = pool.get(session)) {
ScriptObjectMirror mirror1 = (ScriptObjectMirror) scripting1.adapt(ScriptContext.class)
.getAttribute("nashorn.global");
try (AutomationScriptingService.Session scripting2 = pool.get(session)) {
ScriptObjectMirror mirror2 = (ScriptObjectMirror) scripting2.adapt(ScriptContext.class)
.getAttribute("nashorn.global");
assertNotEquals(mirror1, mirror2);
}
}
}
@Test
public void testAutomationCtxSharing() throws Exception {
try (InputStream stream = this.getClass().getResourceAsStream("/shareAutomationContext.js")) {
org.junit.Assert.assertNotNull(stream);
try (AutomationScriptingService.Session scripting = pool.get(session)) {
Object result = scripting.run(stream);
assertEquals("OK", result);
}
}
}
}