1 package jep.test; 2 3 import jep.Interpreter; 4 import jep.JepConfig; 5 import jep.SubInterpreter; 6 7 /** 8 * Tests that shared modules can be imported simultaneously on multiple threads. 9 * Python 3 requires careful synchronization to ensure that uninitialized 10 * modules are not inadvertantly shared. 11 * 12 * This test relies on multiple threads importing at the same time. If the OS 13 * thread scheduling gets lucky it might pass even if there are problems. We 14 * just assume that over the course of a release if it breaks eventually someone 15 * will see a failed test. 16 * 17 * Created: August 2016 18 * 19 * @author Ben Steffensmeier 20 */ 21 public class TestSharedModulesThreads extends Thread { 22 main(String[] args)23 public static void main(String[] args) throws Throwable { 24 TestSharedModulesThreads[] t = new TestSharedModulesThreads[16]; 25 for (int i = 0; i < t.length; i += 1) { 26 t[i] = new TestSharedModulesThreads(); 27 t[i].start(); 28 } 29 for (int i = 0; i < t.length; i += 1) { 30 t[i].join(); 31 if (t[i].e != null) { 32 throw t[i].e; 33 } 34 } 35 /* 36 * Ensure that the shared moduler import hooks don't interfere with pure 37 * python threading. This use case is not well supported but it mostly 38 * works so this just checks for obvious flaws. 39 */ 40 try (Interpreter interp = new SubInterpreter( 41 new JepConfig().addIncludePaths(".") 42 .addSharedModules("xml.etree.ElementTree"))) { 43 interp.eval("import threading"); 44 interp.eval("success = False"); 45 StringBuilder testFunction = new StringBuilder(); 46 testFunction.append("def testFunction():\n"); 47 testFunction.append(" global success\n"); 48 testFunction.append(" import struct\n"); 49 testFunction.append(" success = True"); 50 interp.eval(testFunction.toString()); 51 interp.eval("t = threading.Thread(target=testFunction)"); 52 interp.eval("t.start()"); 53 interp.eval("t.join()"); 54 /* 55 * Sleep to workaround a python bug, that occasionally fails the 56 * test. Remove the sleep when 2.7 and 3.3 are no longer supported. 57 * https://bugs.python.org/issue18808 58 */ 59 Thread.sleep(10); 60 Object success = interp.getValue("success"); 61 if (!Boolean.TRUE.equals(success)) { 62 System.exit(1); 63 } 64 } 65 66 } 67 68 public Exception e = null; 69 70 @Override run()71 public void run() { 72 try (Interpreter interp = new SubInterpreter( 73 new JepConfig().addIncludePaths(".") 74 .addSharedModules("xml.etree.ElementTree"))) { 75 interp.eval("import xml.etree.ElementTree"); 76 interp.eval("t = xml.etree.ElementTree.ElementTree"); 77 } catch (Exception e) { 78 this.e = e; 79 } 80 } 81 82 } 83