You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by dd...@apache.org on 2017/10/03 19:31:46 UTC

[3/6] incubator-freemarker git commit: Fixed template interruption test (could hang if the template fails for some reason).

Fixed template interruption test (could hang if the template fails for some reason).


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/c01f1a22
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/c01f1a22
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/c01f1a22

Branch: refs/heads/2.3
Commit: c01f1a223a04dcff27eb3b71bbbdc759c1628384
Parents: 1375060
Author: ddekany <dd...@apache.org>
Authored: Tue Oct 3 19:50:40 2017 +0200
Committer: ddekany <dd...@apache.org>
Committed: Tue Oct 3 19:54:13 2017 +0200

----------------------------------------------------------------------
 .../core/TheadInterruptingSupportTest.java      | 162 ----------------
 .../core/ThreadInterruptingSupportTest.java     | 184 +++++++++++++++++++
 2 files changed, 184 insertions(+), 162 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/c01f1a22/src/test/java/freemarker/core/TheadInterruptingSupportTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/TheadInterruptingSupportTest.java b/src/test/java/freemarker/core/TheadInterruptingSupportTest.java
deleted file mode 100644
index cbba0c3..0000000
--- a/src/test/java/freemarker/core/TheadInterruptingSupportTest.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * 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 freemarker.core;
-
-import static org.junit.Assert.*;
-
-import java.io.IOException;
-import java.util.Map;
-
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import freemarker.core.ThreadInterruptionSupportTemplatePostProcessor.TemplateProcessingThreadInterruptedException;
-import freemarker.template.Configuration;
-import freemarker.template.Template;
-import freemarker.template.TemplateDirectiveBody;
-import freemarker.template.TemplateDirectiveModel;
-import freemarker.template.TemplateException;
-import freemarker.template.TemplateModel;
-import freemarker.template.utility.NullWriter;
-
-public class TheadInterruptingSupportTest {
-    
-    private static final Logger LOG = LoggerFactory.getLogger(TheadInterruptingSupportTest.class);
-
-    private static final int TEMPLATE_INTERRUPTION_TIMEOUT = 5000;
-    private final Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
-
-    @Test
-    public void test() throws IOException, InterruptedException {
-        assertCanBeInterrupted("<#list 1.. as x></#list>");
-        assertCanBeInterrupted("<#list 1.. as x>${x}</#list>");
-        assertCanBeInterrupted("<#list 1.. as x>t${x}</#list>");
-        assertCanBeInterrupted("<#list 1.. as x><#list 1.. as y>${y}</#list></#list>");
-        assertCanBeInterrupted("<#list 1.. as x>${x}<#else>nope</#list>");
-        assertCanBeInterrupted("<#list 1..>[<#items as x>${x}</#items>]<#else>nope</#list>");
-        assertCanBeInterrupted("<@customLoopDirective />");
-        assertCanBeInterrupted("<@customLoopDirective>x</@>");
-        assertCanBeInterrupted("<@customLoopDirective><#if true>x</#if></@>");
-        assertCanBeInterrupted("<#macro selfCalling><@sleepDirective/><@selfCalling /></#macro><@selfCalling />");
-        assertCanBeInterrupted("<#function selfCalling><@sleepDirective/>${selfCalling()}</#function>${selfCalling()}");
-        assertCanBeInterrupted("<#list 1.. as _><#attempt><@sleepDirective/><#recover>suppress</#attempt></#list>");
-        assertCanBeInterrupted("<#attempt><#list 1.. as _></#list><#recover>suppress</#attempt>");
-    }
-
-    private void assertCanBeInterrupted(final String templateSourceCode) throws IOException, InterruptedException {
-        TemplateRunnerThread trt = new TemplateRunnerThread(templateSourceCode);
-        trt.start();
-        synchronized (trt) {
-            while (!trt.isStarted()) {
-                trt.wait();
-            }
-        }
-        Thread.sleep(50); // Just to ensure (hope...) that the template execution reaches "deep" enough
-        trt.interrupt();
-        trt.join(TEMPLATE_INTERRUPTION_TIMEOUT);
-        assertTrue(trt.isTemplateProcessingInterrupted());
-    }
-
-    public class TemplateRunnerThread extends Thread {
-
-        private final Template template;
-        private boolean started;
-        private boolean templateProcessingInterrupted;
-
-        public TemplateRunnerThread(String templateSourceCode) throws IOException {
-            template = new Template(null, "<@startedDirective/>" + templateSourceCode, cfg);
-            _CoreAPI.addThreadInterruptedChecks(template);
-        }
-
-        @Override
-        public void run() {
-            try {
-                template.process(this, NullWriter.INSTANCE);
-            } catch (TemplateProcessingThreadInterruptedException e) {
-                //LOG.debug("Template processing interrupted", e);
-                synchronized (this) {
-                    templateProcessingInterrupted = true;
-                }
-            } catch (Throwable e) {
-                LOG.error("Template processing failed", e);
-            }
-        }
-
-        public synchronized boolean isTemplateProcessingInterrupted() {
-            return templateProcessingInterrupted;
-        }
-        
-        public synchronized boolean isStarted() {
-            return started;
-        }
-        
-        public TemplateDirectiveModel getStartedDirective() {
-            return new StartedDirective();
-        }
-
-        public TemplateDirectiveModel getCustomLoopDirective() {
-            return new CustomLoopDirective();
-        }
-        
-        public TemplateDirectiveModel getSleepDirective() {
-            return new SleepDirective();
-        }
-
-        public class StartedDirective implements TemplateDirectiveModel {
-            
-            public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)
-                    throws TemplateException, IOException {
-                synchronized (TemplateRunnerThread.this) {
-                    started = true;
-                    TemplateRunnerThread.this.notifyAll();
-                }
-            }
-            
-        }
-
-        public class CustomLoopDirective implements TemplateDirectiveModel {
-
-            public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)
-                    throws TemplateException, IOException {
-                while (true) {
-                    body.render(NullWriter.INSTANCE);
-                }
-            }
-            
-        }
-        
-        public class SleepDirective implements TemplateDirectiveModel {
-
-            public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)
-                    throws TemplateException, IOException {
-                try {
-                    Thread.sleep(100);
-                } catch (InterruptedException e) {
-                    // Thread.sleep has reset the interrupted flag (because it has thrown InterruptedException).  
-                    Thread.currentThread().interrupt();
-                }
-            }
-            
-        }
-        
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/c01f1a22/src/test/java/freemarker/core/ThreadInterruptingSupportTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/ThreadInterruptingSupportTest.java b/src/test/java/freemarker/core/ThreadInterruptingSupportTest.java
new file mode 100644
index 0000000..6b9d86a
--- /dev/null
+++ b/src/test/java/freemarker/core/ThreadInterruptingSupportTest.java
@@ -0,0 +1,184 @@
+/*
+ * 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 freemarker.core;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import freemarker.core.ThreadInterruptionSupportTemplatePostProcessor.TemplateProcessingThreadInterruptedException;
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateDirectiveBody;
+import freemarker.template.TemplateDirectiveModel;
+import freemarker.template.TemplateException;
+import freemarker.template.TemplateModel;
+import freemarker.template.utility.NullWriter;
+
+public class ThreadInterruptingSupportTest {
+    
+    private static final Logger LOG = LoggerFactory.getLogger(ThreadInterruptingSupportTest.class);
+
+    private static final int TEMPLATE_INTERRUPTION_TIMEOUT = 5000;
+    private final Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
+
+    @Test
+    public void test() throws IOException, InterruptedException, TemplateException {
+        assertCanBeInterrupted("<#list 1.. as x></#list>");
+        assertCanBeInterrupted("<#list 1.. as x>${x}</#list>");
+        assertCanBeInterrupted("<#list 1.. as x>t${x}</#list>");
+        assertCanBeInterrupted("<#list 1.. as x><#list 1.. as y>${y}</#list></#list>");
+        assertCanBeInterrupted("<#list 1.. as x>${x}<#else>nope</#list>");
+        assertCanBeInterrupted("<#list 1..>[<#items as x>${x}</#items>]<#else>nope</#list>");
+        assertCanBeInterrupted("<@customLoopDirective />");
+        assertCanBeInterrupted("<@customLoopDirective>x</@>");
+        assertCanBeInterrupted("<@customLoopDirective><#if true>x</#if></@>");
+        assertCanBeInterrupted("<#macro selfCalling><@sleepDirective/><@selfCalling /></#macro><@selfCalling />");
+        assertCanBeInterrupted("<#function selfCalling><@sleepDirective/>${selfCalling()}</#function>${selfCalling()}");
+        assertCanBeInterrupted("<#list 1.. as _><#attempt><@sleepDirective/><#recover>suppress</#attempt></#list>");
+        assertCanBeInterrupted("<#attempt><#list 1.. as _></#list><#recover>suppress</#attempt>");
+    }
+
+    private void assertCanBeInterrupted(final String templateSourceCode)
+            throws IOException, InterruptedException, TemplateException {
+        TemplateRunnerThread trt = new TemplateRunnerThread(templateSourceCode);
+        trt.start();
+        synchronized (trt) {
+            while (!trt.isStartedOrFailed()) {
+                trt.wait();
+            }
+        }
+        if (trt.failedWith != null) {
+            if (trt.failedWith instanceof TemplateException) {
+                throw (TemplateException) trt.failedWith;
+            } else if (trt.failedWith instanceof IOException) {
+                throw (IOException) trt.failedWith;
+            } else {
+                throw new RuntimeException("Template processing has failed", trt.failedWith);
+            }
+        }
+        Thread.sleep(50); // Just to ensure (hope...) that the template execution reaches "deep" enough
+        trt.interrupt();
+        trt.join(TEMPLATE_INTERRUPTION_TIMEOUT);
+        assertTrue(trt.isTemplateProcessingInterrupted());
+    }
+
+    public class TemplateRunnerThread extends Thread {
+
+        private final Template template;
+        private boolean started;
+        private Throwable failedWith;
+        private boolean templateProcessingInterrupted;
+
+        public TemplateRunnerThread(String templateSourceCode) throws IOException {
+            template = new Template(null, "<@startedDirective/>" + templateSourceCode, cfg);
+            _CoreAPI.addThreadInterruptedChecks(template);
+        }
+
+        @Override
+        public void run() {
+            try {
+                template.process(this, NullWriter.INSTANCE);
+            } catch (TemplateProcessingThreadInterruptedException e) {
+                //LOG.debug("Template processing interrupted", e);
+                synchronized (this) {
+                    templateProcessingInterrupted = true;
+                }
+            } catch (Throwable e) {
+                LOG.error("Template processing failed", e);
+                synchronized (TemplateRunnerThread.this) {
+                    failedWith = e;
+                    TemplateRunnerThread.this.notifyAll();
+                }
+            } finally {
+                synchronized (TemplateRunnerThread.this) {
+                    if (!started && failedWith == null) {
+                        failedWith = new IllegalStateException("Start directive was never called");
+                        TemplateRunnerThread.this.notifyAll();
+                    }
+                }
+            }
+        }
+
+        public synchronized boolean isTemplateProcessingInterrupted() {
+            return templateProcessingInterrupted;
+        }
+        
+        public synchronized boolean isStartedOrFailed() {
+            return started || failedWith != null;
+        }
+        
+        public TemplateDirectiveModel getStartedDirective() {
+            return new StartedDirective();
+        }
+
+        public TemplateDirectiveModel getCustomLoopDirective() {
+            return new CustomLoopDirective();
+        }
+        
+        public TemplateDirectiveModel getSleepDirective() {
+            return new SleepDirective();
+        }
+
+        public class StartedDirective implements TemplateDirectiveModel {
+            
+            public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)
+                    throws TemplateException, IOException {
+                synchronized (TemplateRunnerThread.this) {
+                    started = true;
+                    TemplateRunnerThread.this.notifyAll();
+                }
+            }
+            
+        }
+
+        public class CustomLoopDirective implements TemplateDirectiveModel {
+
+            public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)
+                    throws TemplateException, IOException {
+                while (true) {
+                    body.render(NullWriter.INSTANCE);
+                }
+            }
+            
+        }
+        
+        public class SleepDirective implements TemplateDirectiveModel {
+
+            public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)
+                    throws TemplateException, IOException {
+                try {
+                    Thread.sleep(100);
+                } catch (InterruptedException e) {
+                    // Thread.sleep has reset the interrupted flag (because it has thrown InterruptedException).  
+                    Thread.currentThread().interrupt();
+                }
+            }
+            
+        }
+        
+    }
+
+}