| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.hadoop.mapred; |
| |
| import static org.junit.Assert.*; |
| |
| import java.io.File; |
| import java.io.FileWriter; |
| import java.io.IOException; |
| |
| import javax.servlet.http.HttpServletResponse; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.hadoop.fs.FileUtil; |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.mortbay.jetty.testing.HttpTester; |
| import org.mortbay.jetty.testing.ServletTester; |
| |
| public class TestTaskLogServlet { |
| private static final Log LOG = LogFactory.getLog(TestTaskLogServlet.class); |
| private ServletTester tester; |
| |
| @Before |
| public void setup() throws Exception { |
| tester = new ServletTester(); |
| tester.setContextPath("/"); |
| tester.addServlet(TaskLogServlet.class, "/tasklog"); |
| tester.start(); |
| } |
| |
| @Test |
| public void testMissingParameters() throws Exception { |
| HttpTester request = new HttpTester(); |
| request.setMethod("GET"); |
| request.setURI("/tasklog"); |
| request.setVersion("HTTP/1.0"); |
| |
| HttpTester response = new HttpTester(); |
| response.parse(tester.getResponses(request.generate())); |
| |
| assertEquals(400,response.getStatus()); |
| } |
| |
| private void setupValidLogs(String attemptIdStr) throws IOException { |
| TaskAttemptID attemptId = TaskAttemptID.forName(attemptIdStr); |
| File logDir = TaskLog.getAttemptDir(attemptId, false); |
| FileUtil.fullyDelete(logDir); |
| logDir.mkdirs(); |
| assertTrue(logDir.exists()); |
| |
| // Now make the logs with some HTML in the output |
| TaskLog.syncLogs(logDir.getAbsolutePath(), attemptId, false); |
| makeLog(new File(logDir, "stderr"), "<b>this is stderr"); |
| makeLog(new File(logDir, "stdout"), "<b>this is stdout"); |
| makeLog(new File(logDir, "syslog"), "<b>this is syslog"); |
| TaskLog.syncLogs(logDir.getAbsolutePath(), attemptId, false); |
| } |
| |
| @Test |
| public void testHtmlLogs() throws Exception { |
| String attemptIdStr = "attempt_123_0001_m_000001_0"; |
| setupValidLogs(attemptIdStr); |
| |
| HttpTester request = new HttpTester(); |
| request.setMethod("GET"); |
| request.setURI("/tasklog?attemptid=" + attemptIdStr); |
| request.setVersion("HTTP/1.0"); |
| |
| // Make sure all the contents show up and properly escaped |
| HttpTester response = doRequest(request); |
| assertEquals(HttpServletResponse.SC_OK, response.getStatus()); |
| assertEquals("text/html; charset=utf-8", response.getHeader("content-type")); |
| assertTrue(response.getContent().contains("<b>this is stderr")); |
| assertTrue(response.getContent().contains("<b>this is stdout")); |
| assertTrue(response.getContent().contains("<b>this is syslog")); |
| |
| // Only read a small chunk of each file <***b>thi***s |
| // (should still be escaped) |
| request.setURI("/tasklog?attemptid=" + attemptIdStr |
| + "&start=1&end=6"); |
| response = doRequest(request); |
| assertEquals(HttpServletResponse.SC_OK, response.getStatus()); |
| assertEquals("text/html; charset=utf-8", response.getHeader("content-type")); |
| assertFalse(response.getContent().contains("<b")); |
| assertFalse(response.getContent().contains("this is")); |
| assertTrue(response.getContent().contains("b>thi</pre>")); |
| } |
| |
| @Test |
| public void testPlaintextLogs() throws Exception { |
| String attemptIdStr = "attempt_123_0001_m_000001_0"; |
| setupValidLogs(attemptIdStr); |
| |
| HttpTester request = new HttpTester(); |
| request.setMethod("GET"); |
| request.setURI("/tasklog?plaintext=true&attemptid=" + attemptIdStr); |
| request.setVersion("HTTP/1.0"); |
| |
| // Make sure all the contents show up and properly escaped |
| HttpTester response = doRequest(request); |
| // Bad request because we require a 'filter' |
| assertEquals(HttpServletResponse.SC_BAD_REQUEST, response.getStatus()); |
| |
| // Try again with filter |
| request.setURI("/tasklog?plaintext=true&filter=stdout&attemptid=" + attemptIdStr); |
| response = doRequest(request); |
| |
| // Response should be text/plain, not be escaped |
| assertEquals("text/plain; charset=utf-8", response.getHeader("content-type")); |
| assertEquals("<b>this is stdout", response.getContent()); |
| |
| // Test range request |
| request.setURI("/tasklog?plaintext=true&filter=stdout" + |
| "&attemptid=" + attemptIdStr + |
| "&start=1&end=6"); |
| response = doRequest(request); |
| |
| // Response should be text/plain, not be escaped |
| assertEquals("text/plain; charset=utf-8", response.getHeader("content-type")); |
| assertEquals("b>thi", response.getContent()); |
| } |
| |
| private HttpTester doRequest(HttpTester request) throws Exception { |
| String reqStr = request.generate(); |
| LOG.info("Testing request: " + reqStr); |
| String respStr = tester.getResponses(reqStr); |
| LOG.info("Response: " + respStr); |
| HttpTester response = new HttpTester(); |
| response.parse(respStr); |
| return response; |
| } |
| |
| private void makeLog(File f, String contents) throws IOException { |
| LOG.info("Creating log at " + f); |
| FileWriter fw = new FileWriter(f); |
| try { |
| fw.write(contents); |
| } finally { |
| fw.close(); |
| } |
| } |
| |
| } |