blob: b95db16dc463c187301d9eab521dbc9571e032a2 [file] [log] [blame]
/**
* 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.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.mapreduce.TaskType;
import org.apache.hadoop.mapreduce.server.tasktracker.TTConfig;
import org.apache.hadoop.security.UnixUserGroupInformation;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class TestDebugScript {
// base directory which is used by the debug script
private static final String BASE_DIR = new File(System.getProperty(
"test.build.data", "/tmp")).getAbsolutePath();
// script directory which is passed as dummy input + where debugscript
// is written.
private static final String SCRIPT_DIR = new File(BASE_DIR, "debugscript")
.getAbsolutePath();
// script which is used as debug script.
private static final String SCRIPT_FILE = new File(SCRIPT_DIR,
"debugscript.sh").getAbsolutePath();
// making an assumption we have bash in path. Same as TaskLog.
// The debug script just accesses the stderr file of the task
// and does a 'cat' on it
private static final String SCRIPT_CONTENT = "cat $2";
@Before
public void setup() throws Exception {
setupDebugScriptDirs();
}
@After
public void tearDown() throws Exception {
cleanupDebugScriptDirs();
}
/**
* Cleanup method which is used to delete the files folder which are generated
* by the testcase.
*
*/
static void cleanupDebugScriptDirs() {
File scriptFile = new File(SCRIPT_FILE);
scriptFile.delete();
File scriptDir = new File(SCRIPT_DIR);
scriptDir.delete();
}
/**
* Setup method which is used to create necessary files and folder for the
* testcase.
*
* @throws Exception
*/
static void setupDebugScriptDirs() throws Exception {
File scriptDir = new File(SCRIPT_DIR);
if (!scriptDir.exists()) {
scriptDir.mkdirs();
}
scriptDir.setExecutable(true, false);
scriptDir.setReadable(true, false);
scriptDir.setWritable(true, false);
File scriptFile = new File(SCRIPT_FILE);
PrintWriter writer = new PrintWriter(scriptFile);
writer.println(SCRIPT_CONTENT);
writer.flush();
writer.close();
scriptFile.setExecutable(true, false);
scriptFile.setReadable(true, false);
}
/**
* Main test case which checks proper execution of the testcase.
*
* @throws Exception
*/
@Test
public void testDebugScript() throws Exception {
JobConf conf = new JobConf();
conf.setLong(TTConfig.TT_SLEEP_TIME_BEFORE_SIG_KILL, 0L);
MiniMRCluster mrCluster = new MiniMRCluster(1, "file:///", 1, null, null, conf);
Path inputPath = new Path(SCRIPT_DIR);
Path outputPath = new Path(SCRIPT_DIR, "task_output");
// Run a failing mapper so debug script is launched.
JobID jobId = runFailingMapJob(mrCluster.createJobConf(), inputPath,
outputPath);
// construct the task id of first map task of failmap
TaskAttemptID taskId = new TaskAttemptID(
new TaskID(jobId,TaskType.MAP, 0), 0);
// verify if debug script was launched correctly and ran correctly.
verifyDebugScriptOutput(taskId);
}
/**
* Method which verifies if debug script ran and ran correctly.
*
* @param taskId
* @param expectedUser
* expected user id from debug script
* @throws Exception
*/
static void verifyDebugScriptOutput(TaskAttemptID taskId) throws Exception {
verifyDebugScriptOutput(taskId, null, null);
}
/**
* Method which verifies if debug script ran and ran correctly.
*
* @param taskId
* @param expectedUser
* expected user id from debug script
* @param expectedPerms the expected permissions on the debugout file
* @throws Exception
*/
static void verifyDebugScriptOutput(TaskAttemptID taskId, String expectedUser,
String expectedPerms) throws Exception {
File output = TaskLog.getRealTaskLogFileLocation(taskId,
TaskLog.LogName.DEBUGOUT);
// Check the presence of the output file if the script is to be run.
assertTrue("Output file does not exists. DebugScript has not been run",
output.exists());
// slurp the output from file, which is one line
BufferedReader reader = new BufferedReader(new FileReader(output));
String out = reader.readLine();
// close the file.
reader.close();
// Check if there is any output
assertNotNull("DebugScript didn't generate output.", out);
assertTrue(out.contains("failing map"));
if (expectedPerms != null && expectedUser != null) {
//check whether the debugout file ownership/permissions are as expected
String ttGroup = UnixUserGroupInformation.login().getGroupNames()[0];
TestTaskTrackerLocalization.checkFilePermissions(output.getAbsolutePath(),
expectedPerms, expectedUser, ttGroup);
}
}
/**
* Method to run a failing mapper on a given Cluster.
*
* @param conf
* the JobConf for the job
* @param inputPath
* input path for the job.
* @param outputDir
* output directory for job.
* @throws IOException
*/
static JobID runFailingMapJob(JobConf conf, Path inputPath, Path outputDir)
throws IOException {
conf.setMapDebugScript(SCRIPT_FILE);
conf.setMaxMapAttempts(0);
conf.set("mapred.committer.job.setup.cleanup.needed", "false");
RunningJob rJob = UtilsForTests.runJobFail(conf, inputPath, outputDir);
return rJob.getID();
}
}