- * First time call it return a wrapped json response with a
- * IllegalArgumentException
- *
- * Second time call it return a valid GET_BLOCK_LOCATIONS
- * json response
- *
- * Third time call it return a wrapped json response with
- * a random IOException
- *
- */
- public static class MockWebHdfsServlet extends HttpServlet {
-
- private static final long serialVersionUID = 1L;
- private static int respondTimes = 0;
- private static final String RANDOM_EXCEPTION_MSG =
- "This is a random exception";
-
- @Override
- public void doGet(HttpServletRequest request,
- HttpServletResponse response) throws ServletException, IOException {
- response.setHeader("Content-Type",
- MediaType.APPLICATION_JSON);
- String param = request.getParameter("op");
- if(respondTimes == 0) {
- Exception mockException = new IllegalArgumentException(
- "Invalid value for webhdfs parameter \"op\". "
- + "" + "No enum constant " + param);
- sendException(request, response, mockException);
- } else if (respondTimes == 1) {
- sendResponse(request, response);
- } else if (respondTimes == 2) {
- Exception mockException = new IOException(RANDOM_EXCEPTION_MSG);
- sendException(request, response, mockException);
- }
- respondTimes++;
- }
-
- private void sendResponse(HttpServletRequest request,
- HttpServletResponse response) throws IOException {
- response.setStatus(HttpServletResponse.SC_OK);
- // Construct a LocatedBlock for testing
- DatanodeInfo d = DFSTestUtil.getLocalDatanodeInfo();
- DatanodeInfo[] ds = new DatanodeInfo[1];
- ds[0] = d;
- ExtendedBlock b1 = new ExtendedBlock("bpid", 1, 121, 1);
- LocatedBlock l1 = new LocatedBlock(b1, ds);
- l1.setStartOffset(0);
- l1.setCorrupt(false);
- List ls = Arrays.asList(l1);
- LocatedBlocks locatedblocks =
- new LocatedBlocks(10, false, ls, l1,
- true, null, null);
-
- try (PrintWriter pw = response.getWriter()) {
- pw.write(JsonUtil.toJsonString(locatedblocks));
- }
- }
-
- private void sendException(HttpServletRequest request,
- HttpServletResponse response,
- Exception mockException) throws IOException {
- response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
- String errJs = JsonUtil.toJsonString(mockException);
- try (PrintWriter pw = response.getWriter()) {
- pw.write(errJs);
- }
- }
- }
-
- @Test
- public void testGetFileBlockLocationsBackwardsCompatibility()
- throws Exception {
- final Configuration conf = WebHdfsTestUtil.createConf();
- final String pathSpec = WebHdfsFileSystem.PATH_PREFIX + "/*";
- HttpServer2 http = null;
- try {
- http = HttpServerFunctionalTest.createTestServer(conf);
- http.addServlet("test", pathSpec, MockWebHdfsServlet.class);
- http.start();
-
- // Write the address back to configuration so
- // WebHdfsFileSystem could connect to the mock server
- conf.set(DFSConfigKeys.DFS_NAMENODE_HTTP_ADDRESS_KEY,
- "localhost:" + http.getConnectorAddress(0).getPort());
-
- final WebHdfsFileSystem webFS = WebHdfsTestUtil.getWebHdfsFileSystem(
- conf, WebHdfsConstants.WEBHDFS_SCHEME);
-
- WebHdfsFileSystem spyFs = spy(webFS);
- BlockLocation[] locations = spyFs
- .getFileBlockLocations(new Path("p"), 0, 100);
-
- // Verify result
- assertEquals(1, locations.length);
- assertEquals(121, locations[0].getLength());
-
- // Verify the fall back
- // The function should be called exactly 2 times
- // 1st time handles GETFILEBLOCKLOCATIONS and found it is not supported
- // 2nd time fall back to handle GET_FILE_BLOCK_LOCATIONS
- verify(spyFs, times(2)).getFileBlockLocations(any(),
- any(), anyLong(), anyLong());
-
- // Verify it doesn't erroneously fall back
- // When server returns a different error, it should directly
- // throw an exception.
- try {
- spyFs.getFileBlockLocations(new Path("p"), 0, 100);
- } catch (Exception e) {
- assertTrue(e instanceof IOException);
- assertEquals(e.getMessage(), MockWebHdfsServlet.RANDOM_EXCEPTION_MSG);
- // Totally this function has been called 3 times
- verify(spyFs, times(3)).getFileBlockLocations(any(),
- any(), anyLong(), anyLong());
- }
- } finally {
- if(http != null) {
- http.stop();
- }
- }
- }
}