public void testDownloadFinishes() throws Exception { BlockingConnectionUtils.keepAllAlive(testUP, pingReplyFactory); // clear up any messages before we begin the test. drainAll(); DatagramPacket pack = null; Message m = null; byte[] guid = searchServices.newQueryGUID(); searchServices.query(guid, "whatever"); // i need to pretend that the UI is showing the user the query still callback.setGUID(new GUID(guid)); QueryRequest qr = BlockingConnectionUtils.getFirstInstanceOfMessageType(testUP[0], QueryRequest.class); assertNotNull(qr); assertTrue(qr.desiresOutOfBandReplies()); // ok, the leaf is sending OOB queries - good stuff, now we should send // a lot of results back and make sure it buffers the bypassed OOB ones for (int i = 0; i < testUP.length; i++) { Response[] res = new Response[200]; for (int j = 0; j < res.length; j++) res[j] = responseFactory.createResponse( 10 + j + i, 10 + j + i, "whatever " + j + i, UrnHelper.SHA1); m = queryReplyFactory.createQueryReply( qr.getGUID(), (byte) 1, 6355, myIP(), 0, res, GUID.makeGuid(), new byte[0], false, false, true, true, false, false, null); testUP[i].send(m); testUP[i].flush(); } // create a test uploader and send back that response TestUploader uploader = new TestUploader(networkManagerStub); uploader.start("whatever", UPLOADER_PORT, false); uploader.setBusy(true); URN urn = TestFile.hash(); RemoteFileDesc rfd = makeRFD(urn); // wait for processing Thread.sleep(1500); // just do it for 1 UDP guy { ReplyNumberVendorMessage vm = replyNumberVendorMessageFactory.createV3ReplyNumberVendorMessage( new GUID(qr.getGUID()), 1); ByteArrayOutputStream baos = new ByteArrayOutputStream(); vm.write(baos); pack = new DatagramPacket( baos.toByteArray(), baos.toByteArray().length, testUP[0].getInetAddress(), SERVER_PORT); UDP_ACCESS[0].send(pack); } // wait for processing Thread.sleep(500); { // all the UDP ReplyNumberVMs should have been bypassed assertByPassedResultsCacheHasSize(qr.getGUID(), 1); } long currTime = System.currentTimeMillis(); Downloader downloader = downloadServices.download(new RemoteFileDesc[] {rfd}, false, new GUID(guid)); final int MAX_TRIES = 60; for (int i = 0; i <= MAX_TRIES; i++) { Thread.sleep(500); if (downloader.getState() == DownloadState.ITERATIVE_GUESSING) break; if (i == MAX_TRIES) fail("didn't GUESS!!"); } // we should get a query key request { boolean gotPing = false; while (!gotPing) { byte[] datagramBytes = new byte[1000]; pack = new DatagramPacket(datagramBytes, 1000); UDP_ACCESS[0].setSoTimeout(10000); // may need to wait UDP_ACCESS[0].receive(pack); InputStream in = new ByteArrayInputStream(pack.getData()); m = messageFactory.read(in, Network.TCP); m.hop(); if (m instanceof PingRequest) gotPing = ((PingRequest) m).isQueryKeyRequest(); } } // send back a query key AddressSecurityToken qk = new AddressSecurityToken(InetAddress.getLocalHost(), SERVER_PORT, macManager); { byte[] ip = new byte[] {(byte) 127, (byte) 0, (byte) 0, (byte) 1}; PingReply pr = pingReplyFactory.createQueryKeyReply( GUID.makeGuid(), (byte) 1, UDP_ACCESS[0].getLocalPort(), ip, 10, 10, false, qk); ByteArrayOutputStream baos = new ByteArrayOutputStream(); pr.write(baos); pack = new DatagramPacket( baos.toByteArray(), baos.toByteArray().length, testUP[0].getInetAddress(), SERVER_PORT); UDP_ACCESS[0].send(pack); } Thread.sleep(500); // ensure that it gets into the OnDemandUnicaster { // now we should make sure MessageRouter retains the key Map _queryKeys = (Map) PrivilegedAccessor.getValue(onDemandUnicaster, "_queryKeys"); assertNotNull(_queryKeys); assertEquals(1, _queryKeys.size()); } byte[] urnQueryGUID = null; { // confirm a URN query boolean gotQuery = false; while (!gotQuery) { byte[] datagramBytes = new byte[1000]; pack = new DatagramPacket(datagramBytes, 1000); UDP_ACCESS[0].setSoTimeout(10000); // may need to wait UDP_ACCESS[0].receive(pack); InputStream in = new ByteArrayInputStream(pack.getData()); m = messageFactory.read(in, Network.TCP); if (m instanceof QueryRequest) { QueryRequest qReq = (QueryRequest) m; Set queryURNs = qReq.getQueryUrns(); gotQuery = queryURNs.contains(urn); if (gotQuery) { gotQuery = qReq.getQueryKey().isFor(InetAddress.getLocalHost(), SERVER_PORT); if (gotQuery) urnQueryGUID = qReq.getGUID(); } } } } assertNotNull(urnQueryGUID); long timeoutVal = 8000 - (System.currentTimeMillis() - currTime); Thread.sleep(timeoutVal > 0 ? timeoutVal : 0); assertEquals(DownloadState.BUSY, downloader.getState()); // purge front end of query callback.clearGUID(); // create a new Uploader to service the download TestUploader uploader2 = new TestUploader(networkManagerStub); uploader2.start("whatever", UPLOADER_PORT + 1, false); uploader2.setRate(100); { // send back a query request, the TestUploader should service upload rfd = makeRFD(urn, UPLOADER_PORT + 1); Response[] res = new Response[] {responseFactory.createResponse(10, 10, "whatever", urn)}; m = queryReplyFactory.createQueryReply( urnQueryGUID, (byte) 1, UPLOADER_PORT + 1, myIP(), 0, res, GUID.makeGuid(), new byte[0], false, false, true, true, false, false, null); ByteArrayOutputStream baos = new ByteArrayOutputStream(); m.write(baos); pack = new DatagramPacket( baos.toByteArray(), baos.toByteArray().length, testUP[0].getInetAddress(), SERVER_PORT); UDP_ACCESS[0].send(pack); } // after a while, the download should finish, the bypassed results // should be discarded Thread.sleep(10000); assertEquals(DownloadState.COMPLETE, downloader.getState()); { // now we should make sure MessageRouter clears the map assertByPassedResultsCacheHasSize(qr.getGUID(), 0); } uploader.stopThread(); }
private ByteBuffer buffer(Message m) throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); m.write(out); out.flush(); return ByteBuffer.wrap(out.toByteArray()); }