org.apache.hadoop.mapred.TestTaskLogsTruncater.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.hadoop.mapred.TestTaskLogsTruncater.java

Source

/**
 * 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 java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.Log;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.filecache.DistributedCache;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FileUtil;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.TaskLog.LogFileDetail;
import org.apache.hadoop.mapred.TaskLog.LogName;
import org.apache.hadoop.mapred.lib.IdentityMapper;
import org.apache.hadoop.mapreduce.server.tasktracker.JVMInfo;
import org.apache.hadoop.mapreduce.server.tasktracker.userlogs.JvmFinishedEvent;
import org.apache.hadoop.mapreduce.server.tasktracker.userlogs.UserLogManager;
import org.apache.hadoop.mapreduce.split.JobSplit;

import org.junit.After;
import org.junit.Ignore;
import org.junit.Test;

import static org.junit.Assert.*;

/**
 * Verify the logs' truncation functionality.
 */
public class TestTaskLogsTruncater {

    static final Log LOG = LogFactory.getLog(TestTaskLogsTruncater.class);
    private static int truncatedMsgSize = TaskLogsTruncater.TRUNCATED_MSG.getBytes().length;

    /**
     * clean-up any stale directories after enabling writable permissions for all
     * attempt-dirs.
     * 
     * @throws IOException
     */
    @After
    public void tearDown() throws IOException {
        File logDir = TaskLog.getUserLogDir();
        for (File attemptDir : logDir.listFiles()) {
            attemptDir.setWritable(true);
            FileUtil.fullyDelete(attemptDir);
        }
    }

    private void writeBytes(TaskAttemptID firstAttemptID, TaskAttemptID attemptID, LogName logName, long numBytes,
            boolean random, char data) throws IOException {

        File logFile = TaskLog.getTaskLogFile(firstAttemptID, false, logName);
        File logLocation = logFile.getParentFile();

        LOG.info("Going to write " + numBytes + " real bytes to the log file " + logFile);

        if (!logLocation.exists() && !logLocation.mkdirs()) {
            throw new IOException("Couldn't create all ancestor dirs for " + logFile);
        }

        File attemptDir = TaskLog.getAttemptDir(attemptID, false);
        if (!attemptDir.exists() && !attemptDir.mkdirs()) {
            throw new IOException("Couldn't create all ancestor dirs for " + logFile);
        }

        // Need to call up front to set currenttaskid.
        TaskLog.syncLogs(logLocation.toString(), attemptID, false, true);

        FileOutputStream outputStream = new FileOutputStream(logFile, true);
        Random r = new Random();
        for (long i = 0; i < numBytes; i++) {
            if (random) {
                outputStream.write(r.nextInt());
            } else {
                outputStream.write(data);
            }
        }
        outputStream.close();
        TaskLog.syncLogs(logLocation.toString(), attemptID, false, true);
        LOG.info("Written " + logFile.length() + " real bytes to the log file " + logFile);
    }

    private void writeRandomBytes(TaskAttemptID firstAttemptID, TaskAttemptID attemptID, LogName logName,
            long numBytes) throws IOException {
        writeBytes(firstAttemptID, attemptID, logName, numBytes, true, ' ');
    }

    private void writeRealChars(TaskAttemptID firstAttemptID, TaskAttemptID attemptID, LogName logName,
            long numChars, char data) throws IOException {
        writeBytes(firstAttemptID, attemptID, logName, numChars, false, data);
    }

    private static Map<LogName, Long> getAllLogsFileLengths(TaskAttemptID tid, boolean isCleanup)
            throws IOException {
        Map<LogName, Long> allLogsFileLengths = new HashMap<LogName, Long>();

        // If the index file doesn't exist, we cannot get log-file lengths. So set
        // them to zero.
        if (!TaskLog.getIndexFile(tid, isCleanup).exists()) {
            for (LogName log : LogName.values()) {
                allLogsFileLengths.put(log, Long.valueOf(0));
            }
            return allLogsFileLengths;
        }

        Map<LogName, LogFileDetail> logFilesDetails = TaskLog.getAllLogsFileDetails(tid, isCleanup);
        for (LogName log : logFilesDetails.keySet()) {
            allLogsFileLengths.put(log, Long.valueOf(logFilesDetails.get(log).length));
        }
        return allLogsFileLengths;
    }

    private Configuration setRetainSizes(long mapRetainSize, long reduceRetainSize) {
        Configuration conf = new Configuration();
        conf.setLong(TaskLogsTruncater.MAP_USERLOG_RETAIN_SIZE, mapRetainSize);
        conf.setLong(TaskLogsTruncater.REDUCE_USERLOG_RETAIN_SIZE, reduceRetainSize);
        return conf;
    }

    /**
     * Test cases which don't need any truncation of log-files. Without JVM-reuse.
     * 
     * @throws IOException
     */
    @Test
    public void testNoTruncationNeeded() throws IOException {
        Configuration conf = setRetainSizes(1000L, 1000L);
        TaskLogsTruncater trunc = new TaskLogsTruncater(conf);

        TaskID baseId = new TaskID();
        int taskcount = 0;

        TaskAttemptID attemptID = new TaskAttemptID(baseId, taskcount++);
        Task task = new MapTask(null, attemptID, 0, new JobSplit.TaskSplitIndex(), 0);

        // Let the tasks write logs within retain-size
        for (LogName log : LogName.values()) {
            writeRandomBytes(attemptID, attemptID, log, 500);
        }
        File logIndex = TaskLog.getIndexFile(attemptID, false);
        long indexModificationTimeStamp = logIndex.lastModified();

        File attemptDir = TaskLog.getAttemptDir(attemptID, false);
        assertTrue(attemptDir + " doesn't exist!", attemptDir.exists());
        assertEquals("index file got modified", indexModificationTimeStamp, logIndex.lastModified());

        // Finish the task and the JVM too.
        JVMInfo jvmInfo = new JVMInfo(attemptDir, Arrays.asList(task));
        trunc.truncateLogs(jvmInfo);

        // There should be no truncation of the log-file.
        assertTrue(attemptDir.exists());
        assertEquals("index file got modified", indexModificationTimeStamp, logIndex.lastModified());

        Map<LogName, Long> logLengths = getAllLogsFileLengths(attemptID, false);
        for (LogName log : LogName.values()) {
            File logFile = TaskLog.getTaskLogFile(attemptID, false, log);
            assertEquals(500, logFile.length());
            // The index file should also be proper.
            assertEquals(500, logLengths.get(log).longValue());
        }

        // truncate it once again
        trunc.truncateLogs(jvmInfo);
        assertEquals("index file got modified", indexModificationTimeStamp, logIndex.lastModified());

        logLengths = getAllLogsFileLengths(attemptID, false);
        for (LogName log : LogName.values()) {
            File logFile = TaskLog.getTaskLogFile(attemptID, false, log);
            assertEquals(500, logFile.length());
            // The index file should also be proper.
            assertEquals(500, logLengths.get(log).longValue());
        }
    }

    /**
     * Test the disabling of truncation of log-file.
     * 
     * @throws IOException
     */
    @Test
    public void testDisabledLogTruncation() throws IOException {
        // Anything less than 0 disables the truncation.
        Configuration conf = setRetainSizes(-1L, -1L);
        TaskLogsTruncater trunc = new TaskLogsTruncater(conf);

        TaskID baseId = new TaskID();
        int taskcount = 0;

        TaskAttemptID attemptID = new TaskAttemptID(baseId, taskcount++);
        Task task = new MapTask(null, attemptID, 0, new JobSplit.TaskSplitIndex(), 0);

        // Let the tasks write some logs
        for (LogName log : LogName.values()) {
            writeRandomBytes(attemptID, attemptID, log, 1500);
        }

        File attemptDir = TaskLog.getAttemptDir(attemptID, false);
        assertTrue(attemptDir + " doesn't exist!", attemptDir.exists());

        // Finish the task and the JVM too.
        JVMInfo jvmInfo = new JVMInfo(attemptDir, Arrays.asList(task));
        trunc.truncateLogs(jvmInfo);

        // The log-file should not be truncated.
        assertTrue(attemptDir.exists());
        Map<LogName, Long> logLengths = getAllLogsFileLengths(attemptID, false);
        for (LogName log : LogName.values()) {
            File logFile = TaskLog.getTaskLogFile(attemptID, false, log);
            assertEquals(1500, logFile.length());
            // The index file should also be proper.
            assertEquals(1500, logLengths.get(log).longValue());
        }
    }

    /**
     * Test the truncation of log-file when JVMs are not reused.
     * 
     * @throws IOException
     */
    @Test
    public void testLogTruncationOnFinishing() throws IOException {
        Configuration conf = setRetainSizes(1000L, 1000L);
        TaskLogsTruncater trunc = new TaskLogsTruncater(conf);

        TaskID baseId = new TaskID();
        int taskcount = 0;

        TaskAttemptID attemptID = new TaskAttemptID(baseId, taskcount++);
        Task task = new MapTask(null, attemptID, 0, new JobSplit.TaskSplitIndex(), 0);

        // Let the tasks write logs more than retain-size
        for (LogName log : LogName.values()) {
            writeRandomBytes(attemptID, attemptID, log, 1500);
        }

        File attemptDir = TaskLog.getAttemptDir(attemptID, false);
        assertTrue(attemptDir + " doesn't exist!", attemptDir.exists());

        // Finish the task and the JVM too.
        JVMInfo jvmInfo = new JVMInfo(attemptDir, Arrays.asList(task));
        trunc.truncateLogs(jvmInfo);

        // The log-file should now be truncated.
        assertTrue(attemptDir.exists());

        Map<LogName, Long> logLengths = getAllLogsFileLengths(attemptID, false);
        for (LogName log : LogName.values()) {
            File logFile = TaskLog.getTaskLogFile(attemptID, false, log);
            assertEquals(1000 + truncatedMsgSize, logFile.length());
            // The index file should also be proper.
            assertEquals(1000 + truncatedMsgSize, logLengths.get(log).longValue());
        }

        // truncate once again
        logLengths = getAllLogsFileLengths(attemptID, false);
        for (LogName log : LogName.values()) {
            File logFile = TaskLog.getTaskLogFile(attemptID, false, log);
            assertEquals(1000 + truncatedMsgSize, logFile.length());
            // The index file should also be proper.
            assertEquals(1000 + truncatedMsgSize, logLengths.get(log).longValue());
        }
    }

    /**
     * Test the truncation of log-file.
     * 
     * It writes two log files and truncates one, does not truncate other. 
     * 
     * @throws IOException
     */
    @Test
    public void testLogTruncation() throws IOException {
        Configuration conf = setRetainSizes(1000L, 1000L);
        TaskLogsTruncater trunc = new TaskLogsTruncater(conf);

        TaskID baseId = new TaskID();
        int taskcount = 0;

        TaskAttemptID attemptID = new TaskAttemptID(baseId, taskcount++);
        Task task = new MapTask(null, attemptID, 0, new JobSplit.TaskSplitIndex(), 0);

        // Let the tasks write logs more than retain-size
        writeRandomBytes(attemptID, attemptID, LogName.SYSLOG, 1500);
        writeRandomBytes(attemptID, attemptID, LogName.STDERR, 500);

        File attemptDir = TaskLog.getAttemptDir(attemptID, false);
        assertTrue(attemptDir + " doesn't exist!", attemptDir.exists());

        // Finish the task and the JVM too.
        JVMInfo jvmInfo = new JVMInfo(attemptDir, Arrays.asList(task));
        trunc.truncateLogs(jvmInfo);

        // The log-file should now be truncated.
        assertTrue(attemptDir.exists());

        Map<LogName, Long> logLengths = getAllLogsFileLengths(attemptID, false);
        File logFile = TaskLog.getTaskLogFile(attemptID, false, LogName.SYSLOG);
        assertEquals(1000 + truncatedMsgSize, logFile.length());
        // The index file should also be proper.
        assertEquals(1000 + truncatedMsgSize, logLengths.get(LogName.SYSLOG).longValue());
        String syslog = TestMiniMRMapRedDebugScript.readTaskLog(LogName.SYSLOG, attemptID, false);
        assertTrue(syslog.startsWith(TaskLogsTruncater.TRUNCATED_MSG));
        logFile = TaskLog.getTaskLogFile(attemptID, false, LogName.STDERR);
        assertEquals(500, logFile.length());
        // The index file should also be proper.
        assertEquals(500, logLengths.get(LogName.STDERR).longValue());
        String stderr = TestMiniMRMapRedDebugScript.readTaskLog(LogName.STDERR, attemptID, false);
        assertFalse(stderr.startsWith(TaskLogsTruncater.TRUNCATED_MSG));

        // truncate once again
        trunc.truncateLogs(jvmInfo);
        logLengths = getAllLogsFileLengths(attemptID, false);
        logFile = TaskLog.getTaskLogFile(attemptID, false, LogName.SYSLOG);
        assertEquals(1000 + truncatedMsgSize, logFile.length());
        // The index file should also be proper.
        assertEquals(1000 + truncatedMsgSize, logLengths.get(LogName.SYSLOG).longValue());
        logFile = TaskLog.getTaskLogFile(attemptID, false, LogName.STDERR);
        assertEquals(500, logFile.length());
        // The index file should also be proper.
        assertEquals(500, logLengths.get(LogName.STDERR).longValue());
    }

    /**
     * Test the truncation of log-file when JVM-reuse is enabled.
     * 
     * @throws IOException
     */
    @Test
    public void testLogTruncationOnFinishingWithJVMReuse() throws IOException {
        Configuration conf = setRetainSizes(150L, 150L);
        TaskLogsTruncater trunc = new TaskLogsTruncater(conf);

        TaskID baseTaskID = new TaskID();
        int attemptsCount = 0;

        // Assuming the job's retain size is 150
        TaskAttemptID attempt1 = new TaskAttemptID(baseTaskID, attemptsCount++);
        Task task1 = new MapTask(null, attempt1, 0, new JobSplit.TaskSplitIndex(), 0);

        // Let the tasks write logs more than retain-size
        writeRealChars(attempt1, attempt1, LogName.SYSLOG, 200, 'A');

        File attemptDir = TaskLog.getAttemptDir(attempt1, false);
        assertTrue(attemptDir + " doesn't exist!", attemptDir.exists());

        // Start another attempt in the same JVM
        TaskAttemptID attempt2 = new TaskAttemptID(baseTaskID, attemptsCount++);
        Task task2 = new MapTask(null, attempt2, 0, new JobSplit.TaskSplitIndex(), 0);
        // Let attempt2 also write some logs
        writeRealChars(attempt1, attempt2, LogName.SYSLOG, 100, 'B');
        // Start yet another attempt in the same JVM
        TaskAttemptID attempt3 = new TaskAttemptID(baseTaskID, attemptsCount++);
        Task task3 = new MapTask(null, attempt3, 0, new JobSplit.TaskSplitIndex(), 0);
        // Let attempt3 also write some logs
        writeRealChars(attempt1, attempt3, LogName.SYSLOG, 225, 'C');
        // Finish the JVM.
        JVMInfo jvmInfo = new JVMInfo(attemptDir, Arrays.asList((new Task[] { task1, task2, task3 })));
        trunc.truncateLogs(jvmInfo);

        // The log-file should now be truncated.
        assertTrue(attemptDir.exists());
        File logFile = TaskLog.getTaskLogFile(attempt1, false, LogName.SYSLOG);
        assertEquals(400 + (2 * truncatedMsgSize), logFile.length());
        // The index files should also be proper.
        assertEquals(150 + truncatedMsgSize,
                getAllLogsFileLengths(attempt1, false).get(LogName.SYSLOG).longValue());
        assertEquals(100, getAllLogsFileLengths(attempt2, false).get(LogName.SYSLOG).longValue());
        assertEquals(150 + truncatedMsgSize,
                getAllLogsFileLengths(attempt3, false).get(LogName.SYSLOG).longValue());

        // assert data for attempt1
        String syslog = TestMiniMRMapRedDebugScript.readTaskLog(LogName.SYSLOG, attempt1, false);
        assertTrue(syslog.startsWith(TaskLogsTruncater.TRUNCATED_MSG));
        String truncatedLog = syslog.substring(truncatedMsgSize);
        for (int i = 0; i < 150; i++) {
            assertEquals("Truncation didn't happen properly. At " + (i + 1) + "th byte, expected 'A' but found "
                    + truncatedLog.charAt(i), 'A', truncatedLog.charAt(i));
        }

        // assert data for attempt2
        syslog = TestMiniMRMapRedDebugScript.readTaskLog(LogName.SYSLOG, attempt2, false);
        for (int i = 0; i < 100; i++) {
            assertEquals("Truncation didn't happen properly. At " + (i + 1) + "th byte, expected 'B' but found "
                    + truncatedLog.charAt(i), 'B', syslog.charAt(i));
        }

        // assert data for attempt3
        syslog = TestMiniMRMapRedDebugScript.readTaskLog(LogName.SYSLOG, attempt3, false);
        assertTrue(syslog.startsWith(TaskLogsTruncater.TRUNCATED_MSG));
        truncatedLog = syslog.substring(truncatedMsgSize);
        for (int i = 0; i < 150; i++) {
            assertEquals("Truncation didn't happen properly. At " + (i + 1) + "th byte, expected 'C' but found "
                    + truncatedLog.charAt(i), 'C', truncatedLog.charAt(i));
        }

        trunc.truncateLogs(jvmInfo);
        // First and third attempts' logs are only truncated, so include 2*length of
        // TRUNCATED_MSG header
        assertEquals(400 + 2 * truncatedMsgSize, logFile.length());
    }

    private static String TEST_ROOT_DIR = new File(System.getProperty("test.build.data", "/tmp")).toURI().toString()
            .replace(' ', '+');

    private static String STDERR_LOG = "stderr log";

    public static class LoggingMapper<K, V> extends IdentityMapper<K, V> {

        public void map(K key, V val, OutputCollector<K, V> output, Reporter reporter) throws IOException {
            // Write lots of logs
            for (int i = 0; i < 1000; i++) {
                System.out.println("Lots of logs! Lots of logs! " + "Waiting to be truncated! Lots of logs!");
            }
            // write some log into stderr
            System.err.println(STDERR_LOG);
            super.map(key, val, output, reporter);
        }
    }

    /**
     * Test logs monitoring with {@link MiniMRCluster}
     * 
     * @throws IOException
     */
    @Test
    @Ignore // Trunction is now done in the Child JVM, because the TaskTracker
            // no longer has write access to the user log dir. MiniMRCluster
            // needs to be modified to put the config params set here in a config
            // on the Child's classpath
    public void testLogsMonitoringWithMiniMR() throws IOException {

        MiniMRCluster mr = null;
        try {
            final long LSIZE = 10000L;
            JobConf clusterConf = new JobConf();
            clusterConf.setLong(TaskLogsTruncater.MAP_USERLOG_RETAIN_SIZE, LSIZE);
            clusterConf.setLong(TaskLogsTruncater.REDUCE_USERLOG_RETAIN_SIZE, LSIZE);
            mr = new MiniMRCluster(1, "file:///", 3, null, null, clusterConf);

            JobConf conf = mr.createJobConf();

            Path inDir = new Path(TEST_ROOT_DIR + "/input");
            Path outDir = new Path(TEST_ROOT_DIR + "/output");
            FileSystem fs = FileSystem.get(conf);
            if (fs.exists(outDir)) {
                fs.delete(outDir, true);
            }
            if (!fs.exists(inDir)) {
                fs.mkdirs(inDir);
            }
            String input = "The quick brown fox jumped over the lazy dog";
            DataOutputStream file = fs.create(new Path(inDir, "part-0"));
            file.writeBytes(input);
            file.close();

            conf.setInputFormat(TextInputFormat.class);
            conf.setOutputKeyClass(LongWritable.class);
            conf.setOutputValueClass(Text.class);

            FileInputFormat.setInputPaths(conf, inDir);
            FileOutputFormat.setOutputPath(conf, outDir);
            conf.setNumMapTasks(1);
            conf.setNumReduceTasks(0);
            conf.setMapperClass(LoggingMapper.class);

            RunningJob job = JobClient.runJob(conf);
            assertTrue(job.getJobState() == JobStatus.SUCCEEDED);
            for (TaskCompletionEvent tce : job.getTaskCompletionEvents(0)) {
                long length = TaskLog.getTaskLogFile(tce.getTaskAttemptId(), false, TaskLog.LogName.STDOUT)
                        .length();
                assertTrue("STDOUT log file length for " + tce.getTaskAttemptId() + " is " + length + " and not <="
                        + LSIZE, length <= LSIZE + truncatedMsgSize);
                if (tce.isMap) {
                    String stderr = TestMiniMRMapRedDebugScript.readTaskLog(LogName.STDERR, tce.getTaskAttemptId(),
                            false);
                    System.out.println("STDERR log:" + stderr);
                    assertTrue(stderr.equals(STDERR_LOG));
                }
            }
        } finally {
            if (mr != null) {
                mr.shutdown();
            }
        }
    }

    /**
     * Test the truncation of DEBUGOUT file by {@link TaskLogsTruncater}
     * @throws IOException 
     */
    @Test
    @Ignore // Trunction is now done in the Child JVM, because the TaskTracker
            // no longer has write access to the user log dir. MiniMRCluster
            // needs to be modified to put the config params set here in a config
            // on the Child's classpath
    public void testDebugLogsTruncationWithMiniMR() throws IOException {

        MiniMRCluster mr = null;
        try {
            final long LSIZE = 10000L;
            JobConf clusterConf = new JobConf();
            clusterConf.setLong(TaskLogsTruncater.MAP_USERLOG_RETAIN_SIZE, LSIZE);
            clusterConf.setLong(TaskLogsTruncater.REDUCE_USERLOG_RETAIN_SIZE, LSIZE);
            mr = new MiniMRCluster(1, "file:///", 3, null, null, clusterConf);

            JobConf conf = mr.createJobConf();

            Path inDir = new Path(TEST_ROOT_DIR + "/input");
            Path outDir = new Path(TEST_ROOT_DIR + "/output");
            FileSystem fs = FileSystem.get(conf);
            if (fs.exists(outDir)) {
                fs.delete(outDir, true);
            }
            if (!fs.exists(inDir)) {
                fs.mkdirs(inDir);
            }
            String input = "The quick brown fox jumped over the lazy dog";
            DataOutputStream file = fs.create(new Path(inDir, "part-0"));
            file.writeBytes(input);
            file.close();

            conf.setInputFormat(TextInputFormat.class);
            conf.setOutputKeyClass(LongWritable.class);
            conf.setOutputValueClass(Text.class);

            FileInputFormat.setInputPaths(conf, inDir);
            FileOutputFormat.setOutputPath(conf, outDir);
            conf.setNumMapTasks(1);
            conf.setMaxMapAttempts(1);
            conf.setNumReduceTasks(0);
            conf.setMapperClass(TestMiniMRMapRedDebugScript.MapClass.class);

            // copy debug script to cache from local file system.
            Path scriptPath = new Path(TEST_ROOT_DIR, "debug-script.txt");
            String debugScriptContent = "for ((i=0;i<1000;i++)); " + "do " + "echo \"Lots of logs! Lots of logs! "
                    + "Waiting to be truncated! Lots of logs!\";" + "done";
            DataOutputStream scriptFile = fs.create(scriptPath);
            scriptFile.writeBytes(debugScriptContent);
            scriptFile.close();
            new File(scriptPath.toUri().getPath()).setExecutable(true);

            URI uri = scriptPath.toUri();
            DistributedCache.createSymlink(conf);
            DistributedCache.addCacheFile(uri, conf);
            conf.setMapDebugScript(scriptPath.toUri().getPath());

            RunningJob job = null;
            try {
                JobClient jc = new JobClient(conf);
                job = jc.submitJob(conf);
                try {
                    jc.monitorAndPrintJob(conf, job);
                } catch (InterruptedException e) {
                    //
                }
            } catch (IOException ioe) {
            } finally {
                for (TaskCompletionEvent tce : job.getTaskCompletionEvents(0)) {
                    File debugOutFile = TaskLog.getTaskLogFile(tce.getTaskAttemptId(), false,
                            TaskLog.LogName.DEBUGOUT);
                    if (debugOutFile.exists()) {
                        long length = debugOutFile.length();
                        assertEquals("DEBUGOUT log file length for " + tce.getTaskAttemptId() + " is " + length
                                + " and not " + LSIZE, length, LSIZE + truncatedMsgSize);
                    }
                }
            }
        } finally {
            if (mr != null) {
                mr.shutdown();
            }
        }
    }
}