|
@@ -20,6 +20,7 @@ package org.apache.hadoop.mapreduce.v2.app.job.impl;
|
|
|
import static org.junit.Assert.assertEquals;
|
|
|
import static org.junit.Assert.assertFalse;
|
|
|
import static org.junit.Assert.assertTrue;
|
|
|
+import static org.junit.Assert.fail;
|
|
|
import static org.mockito.Mockito.mock;
|
|
|
import static org.mockito.Mockito.when;
|
|
|
|
|
@@ -127,8 +128,13 @@ public class TestTaskImpl {
|
|
|
@Override
|
|
|
protected int getMaxAttempts() {
|
|
|
return 100;
|
|
|
- }
|
|
|
-
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void internalError(TaskEventType type) {
|
|
|
+ super.internalError(type);
|
|
|
+ fail("Internal error: " + type);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private class MockTaskAttemptImpl extends TaskAttemptImpl {
|
|
@@ -462,5 +468,32 @@ public class TestTaskImpl {
|
|
|
|
|
|
assertTaskSucceededState();
|
|
|
}
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testSpeculativeTaskAttemptSucceedsEvenIfFirstFails() {
|
|
|
+ TaskId taskId = getNewTaskID();
|
|
|
+ scheduleTaskAttempt(taskId);
|
|
|
+ launchTaskAttempt(getLastAttempt().getAttemptId());
|
|
|
+ updateLastAttemptState(TaskAttemptState.RUNNING);
|
|
|
+
|
|
|
+ // Add a speculative task attempt that succeeds
|
|
|
+ mockTask.handle(new TaskTAttemptEvent(getLastAttempt().getAttemptId(),
|
|
|
+ TaskEventType.T_ADD_SPEC_ATTEMPT));
|
|
|
+ launchTaskAttempt(getLastAttempt().getAttemptId());
|
|
|
+ commitTaskAttempt(getLastAttempt().getAttemptId());
|
|
|
+ mockTask.handle(new TaskTAttemptEvent(getLastAttempt().getAttemptId(),
|
|
|
+ TaskEventType.T_ATTEMPT_SUCCEEDED));
|
|
|
+
|
|
|
+ // The task should now have succeeded
|
|
|
+ assertTaskSucceededState();
|
|
|
+
|
|
|
+ // Now fail the first task attempt, after the second has succeeded
|
|
|
+ mockTask.handle(new TaskTAttemptEvent(taskAttempts.get(0).getAttemptId(),
|
|
|
+ TaskEventType.T_ATTEMPT_FAILED));
|
|
|
+
|
|
|
+ // The task should still be in the succeeded state
|
|
|
+ assertTaskSucceededState();
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
}
|