package water; import org.junit.BeforeClass; import org.junit.Test; import water.fvec.Frame; import water.fvec.TestFrameBuilder; import water.fvec.Vec; import java.io.IOException; import java.nio.channels.ByteChannel; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class ExternalFrameReaderClientTest extends TestUtil{ @BeforeClass() public static void setup() { stall_till_cloudsize(3); } // We keep this one for assertion errors occurred in different threads private volatile AssertionError exc; @Test public void testReading() throws IOException, InterruptedException, ExternalFrameConfirmationException { final String frameName = "testFrame"; final long[] chunkLayout = {2, 2, 2, 1}; final Frame testFrame = new TestFrameBuilder() .withName(frameName) .withColNames("ColA", "ColB") .withVecTypes(Vec.T_NUM, Vec.T_STR) .withDataForCol(0, ard(Double.NaN, 1, 2, 3, 4, 5.6, 7, -1, 3.14)) .withDataForCol(1, ar("A", "B", "C", "E", "F", "I", "J", "\u0000", null)) .withChunkLayout(chunkLayout) .build(); // create frame final String[] nodes = new String[H2O.CLOUD._memary.length]; // get ip and ports of h2o nodes for (int i = 0; i < nodes.length; i++) { nodes[i] = H2O.CLOUD._memary[i].getIpPortString(); } final int[] selectedColumnIndices = {0, 1}; // specify expected types for selected columns final byte[] expectedTypes = {ExternalFrameUtils.EXPECTED_DOUBLE, ExternalFrameUtils.EXPECTED_STRING}; final int nChunks = testFrame.anyVec().nChunks(); // we will read from all chunks at the same time Thread[] threads = new Thread[nChunks]; try { // open all connections in connStrings array for (int idx = 0; idx < nChunks; idx++) { final int currentChunkIdx = idx; threads[idx] = new Thread() { @Override public void run() { try { ByteChannel sock = ExternalFrameUtils.getConnection(nodes[currentChunkIdx % nodes.length]); ExternalFrameReaderClient reader = new ExternalFrameReaderClient(sock, frameName, currentChunkIdx, selectedColumnIndices, expectedTypes); int rowsRead = 0; assertEquals(reader.getNumRows(), chunkLayout[currentChunkIdx]); while (rowsRead < reader.getNumRows()) { if (rowsRead == 0 & currentChunkIdx == 0) { reader.readDouble(); assertTrue("[0,0] in chunk 0 should be NA", reader.isLastNA()); } else { reader.readDouble(); assertFalse("Should not be NA", reader.isLastNA()); } reader.readString(); assertFalse("Should not be NA", reader.isLastNA()); rowsRead++; } assertEquals("Num or rows read was " + rowsRead + ", expecting " + reader.getNumRows(), rowsRead, reader.getNumRows()); reader.waitUntilAllReceived(10); sock.close(); } catch (AssertionError e) { exc = e; } catch (ExternalFrameConfirmationException e){ e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }; threads[idx].start(); } // wait for all writer thread to finish for (Thread t : threads) { t.join(); if (exc != null) { throw exc; } } }finally { testFrame.remove(); } } }