package test_streamer.client.handler; import net.unit8.wscl.WebSocketClassLoader; import org.junit.runner.JUnitCore; import test_streamer.client.*; import test_streamer.client.dto.ResultCommand; import us.bpsm.edn.Keyword; import javax.websocket.DeploymentException; import javax.websocket.Session; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import static test_streamer.client.ClientConfig.ClientConfigKey.CLASS_PROVIDER_URL; /** * @author kawasima */ public class DoTestHandler implements Handler { private static Map<UUID, ClassLoader> classLoaderCache = new HashMap<UUID, ClassLoader>(); private ClientConfig config; private List<ClientUI> uiList; public DoTestHandler(ClientConfig config, List<ClientUI> uiList) { this.config = config; this.uiList = uiList; } @Override public void handle(Map<Keyword, Object> msg, Session session) { String className = msg.get(Keyword.newKeyword("name")).toString(); uiList.forEach(ui -> ui.beginTest(className)); ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); UUID classLoaderId = (UUID) msg.get(Keyword.newKeyword("classloader-id")); String url = new StringBuilder(256) .append(config.getString(CLASS_PROVIDER_URL)) .append("?classLoaderId=") .append(classLoaderId).toString(); ClassLoader loader = classLoaderCache.get(classLoaderId); if (loader == null) { try { loader = new WebSocketClassLoader(url); } catch (IOException | DeploymentException e) { throw new IllegalStateException(e); } } ClientRunListener runListener = new ClientRunListener(className); try { Class<?> testClass = loader.loadClass(className); Thread.currentThread().setContextClassLoader(loader); JUnitCore core = new JUnitCore(); core.addListener(runListener); core.run(testClass); classLoaderCache.put(classLoaderId, loader); } catch(Exception ex) { runListener.getResult().setClientException(ex.getMessage()); } finally { Thread.currentThread().setContextClassLoader(originalClassLoader); } uiList.forEach(ui -> ui.endTest(runListener.getResult())); ResultCommand command = new ResultCommand(className, (UUID) msg.get(Keyword.newKeyword("shot-id"))); command.setResult(runListener.getResult()); WebSocketUtil.send(session, command); uiList.forEach(ClientUI::standby); } public void dispose() { for (Map.Entry<UUID, ClassLoader> entry : classLoaderCache.entrySet()) { if (entry.getValue() instanceof WebSocketClassLoader) { try { ((WebSocketClassLoader) entry.getValue()).dispose(); } catch (IOException e) { throw new IllegalStateException(e); } } } } }