[RServi] Add test case for crashed engines

Change-Id: I809bd0f9f756ad2aac1eaf24f1e7342ffdfee1e4
diff --git a/servi/org.eclipse.statet.rj.servi-tests/src/org/eclipse/statet/rj/servi/pool/JMPoolTest.java b/servi/org.eclipse.statet.rj.servi-tests/src/org/eclipse/statet/rj/servi/pool/JMPoolTest.java
index 2ae7870..fd8fab4 100644
--- a/servi/org.eclipse.statet.rj.servi-tests/src/org/eclipse/statet/rj/servi/pool/JMPoolTest.java
+++ b/servi/org.eclipse.statet.rj.servi-tests/src/org/eclipse/statet/rj/servi/pool/JMPoolTest.java
@@ -15,6 +15,7 @@
 package org.eclipse.statet.rj.servi.pool;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -169,7 +170,7 @@
 	}
 	
 	@Test
-	public void closed() throws Exception {
+	public void RServi_closed() throws Exception {
 		final PoolConfig poolConfig= new PoolConfig();
 		this.server.setPoolConfig(poolConfig);
 		this.server.start();
@@ -394,6 +395,51 @@
 		}
 	}
 	
+	@Test
+	public void handleCrashedEngine() throws Exception {
+		final PoolConfig poolConfig= new PoolConfig();
+		poolConfig.setMaxTotalCount(1);
+		poolConfig.setMaxUsageCount(1);
+		this.server.setPoolConfig(poolConfig);
+		this.server.start();
+		
+		final RServi servi1= getServi("test1");
+		final ProgressMonitor m= new NullProgressMonitor();
+		assertNodeOperative(servi1, m);
+		
+		final PoolNodeObject node1= assertSinglePoolNode();
+		
+		final var clientState= new AtomicInteger();
+		final var clientWorker= CompletableFuture.supplyAsync(() -> {
+			clientState.set(1);
+			try {
+				servi1.evalVoid("while (true) { Sys.sleep(1) }", m);
+				return null;
+			}
+			catch (final StatusException e) {
+				return e;
+			}
+			finally {
+				clientState.set(2);
+			}
+		});
+		while (clientState.get() == 0) {
+			Thread.sleep(100);
+		}
+		
+		final Accessor nodeHandler= new Accessor(node1.getNodeHandler(), NodeHandler.class);
+		final Process process= nonNullAssert((Process)nodeHandler.getFieldObj("process"));
+		process.destroy();
+		
+		assertTrue((clientWorker.get(1, TimeUnit.SECONDS) instanceof StatusException));
+		if (!servi1.isClosed()) {
+			closeServi(servi1);
+		}
+		assertNotEquals(PoolNodeState.ALLOCATED, node1.getState());
+		skipChecking(node1);
+		assertEquals(PoolNodeState.DISPOSED, node1.getState());
+	}
+	
 	
 	@Test
 	public void PoolNode_getState() throws Exception {
@@ -411,6 +457,7 @@
 		assertEquals(PoolNodeState.ALLOCATED, node1.getState());
 		
 		closeServi(servi1);
+		assertNotEquals(PoolNodeState.ALLOCATED, node1.getState());
 		skipChecking(node1);
 		assertEquals(PoolNodeState.IDLING, node1.getState());
 		
@@ -485,7 +532,6 @@
 		this.server.start();
 		
 		final RServi servi1= getServi("test1");
-		
 		final ProgressMonitor m= new NullProgressMonitor();
 		assertNodeOperative(servi1, m);
 		
@@ -518,7 +564,7 @@
 	}
 	
 	@Test
-	public void PoolNode_evictCrashed() throws Exception {
+	public void PoolNode_evictCrashedEngine() throws Exception {
 		final PoolConfig poolConfig= new PoolConfig();
 		poolConfig.setMinIdleCount(0);
 		this.server.setPoolConfig(poolConfig);