Author: mduerig
Date: Thu Mar 10 15:42:51 2011
New Revision: 1080252

URL: http://svn.apache.org/viewvc?rev=1080252&view=rev
Log:
SLING-2012 Sling Scala Hello World example concurrent access fails
adding unit test demonstrating the issue

Added:
    
sling/trunk/contrib/scripting/scala/script/src/test/scala/org/apache/sling/scripting/scala/ScriptEngineTest.scala

Added: 
sling/trunk/contrib/scripting/scala/script/src/test/scala/org/apache/sling/scripting/scala/ScriptEngineTest.scala
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/scala/script/src/test/scala/org/apache/sling/scripting/scala/ScriptEngineTest.scala?rev=1080252&view=auto
==============================================================================
--- 
sling/trunk/contrib/scripting/scala/script/src/test/scala/org/apache/sling/scripting/scala/ScriptEngineTest.scala
 (added)
+++ 
sling/trunk/contrib/scripting/scala/script/src/test/scala/org/apache/sling/scripting/scala/ScriptEngineTest.scala
 Thu Mar 10 15:42:51 2011
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.sling.scripting.scala
+
+import javax.script.{ ScriptEngineFactory, ScriptEngine, ScriptContext, 
Bindings }
+import java.io.StringWriter
+import java.util.ServiceLoader
+import java.util.concurrent.{ TimeUnit, Executors, Callable, Future }
+import junit.framework.TestCase
+import junit.framework.Assert._
+
+import scala.collection.JavaConversions._
+
+/**
+ * JSR 223 compliance test
+ *
+ * <br>
+ *
+ * there is no direct reference to the ScalaScriptingEngine
+ *
+ */
+class ScriptEngineTest extends TestCase {
+
+  implicit def fun2Call[R](f: () => R) = new Callable[R] { def call: R = f() }
+
+  def getScriptEngine(): ScriptEngine = {
+
+    var scriptEngine: ScriptEngine = null;
+
+    for (val load <- ServiceLoader.load(classOf[ScriptEngineFactory])) yield 
load.getEngineName match {
+      case "Scala Scripting Engine" => scriptEngine = load.getScriptEngine;
+      case _ => ; //ignore other script engines
+    };
+
+    assertNotNull(scriptEngine)
+    scriptEngine
+  }
+
+  /**
+   *  tests a simple piece of code
+   *
+   *  this can be used as a reference for how to build a valid string that 
contains scala code for the ScalaScriptingEngine
+   */
+  def testSimple() {
+
+    val scriptEngine: ScriptEngine = getScriptEngine();
+
+    var code = new StringBuilder();
+    code.append("package org.apache.sling.scripting.scala{");
+    code.append("\n");
+    code.append("class Script(args: ScriptArgs) {");
+    code.append("\n");
+    code.append("import args._");
+    code.append("\n");
+    code.append("println(\"output:\" + obj.saySomething()) ");
+    code.append("\n");
+    code.append("}}");
+
+    val say = "hello";
+
+    val b = scriptEngine.getBindings(ScriptContext.ENGINE_SCOPE);
+    b.put("obj", new TestInject(say));
+
+    val writer = new StringWriter();
+    scriptEngine.getContext().setWriter(writer);
+
+    scriptEngine.eval(code.toString(), b)
+    assertEquals("output:" + say, writer.toString.trim())
+  }
+
+  /**
+   * multi-threaded test
+   *
+   * the purpose of this test is to demonstrate the capabilities/faults that 
the current ScalaScriptingEngine implementation has.
+   */
+  def testMultipleThreads() {
+
+    var code = new StringBuilder();
+    code.append("package org.apache.sling.scripting.scala{");
+    code.append("\n");
+    code.append("class Script(args: ScriptArgs) {");
+    code.append("\n");
+    code.append("import args._");
+    code.append("\n");
+    code.append("println(\"output:\" + obj.saySomething()) ");
+    code.append("\n");
+    code.append("}}");
+
+    val threads = 2;
+    val operations = 100;
+    val e = Executors.newFixedThreadPool(threads);
+    var futures = List[Future[Boolean]]();
+
+    for (i <- 0 to operations) {
+      val say = i % 3 match {
+        case 0 => "hello"
+        case 1 => "you again"
+        case 2 => "bye"
+      }
+      val c: Callable[Boolean] = () => buildSayCallable(code.toString, say);
+      val f: Future[Boolean] = e.submit(c);
+      futures = f :: futures;
+    }
+    e.shutdown();
+    e.awaitTermination(120, TimeUnit.SECONDS);
+
+    futures.foreach(f => {
+      try {
+        assertTrue(f.get(10, TimeUnit.SECONDS))
+      } catch {
+        case e: Exception => { e.printStackTrace; fail(e.getMessage); }
+      }
+    });
+  }
+
+  def buildSayCallable(code: String, say: String): Boolean = {
+
+    val scriptEngine: ScriptEngine = getScriptEngine
+    println("thread executing with engine: " + scriptEngine + ", say: " + say);
+
+    val b = scriptEngine.getBindings(ScriptContext.ENGINE_SCOPE);
+    b.put("obj", new TestInject(say));
+
+    val writer = new StringWriter();
+    scriptEngine.getContext().setWriter(writer);
+
+    scriptEngine.eval(code.toString(), b)
+    return "output:" + say == writer.toString.trim();
+  };
+
+  class TestInject(sayWhat: String) {
+    def saySomething() = sayWhat;
+  }
+
+}
+


Reply via email to