| /** |
| * 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.mockito.Mockito.*; |
| |
| import java.io.IOException; |
| |
| import junit.framework.TestCase; |
| |
| import org.apache.hadoop.mapred.UtilsForTests.FakeClock; |
| import org.apache.hadoop.mapreduce.server.jobtracker.JTConfig; |
| import org.apache.hadoop.mapreduce.server.jobtracker.TaskTracker; |
| import org.hamcrest.Matcher; |
| import org.mockito.ArgumentCaptor; |
| import org.mockito.ArgumentMatcher; |
| |
| /** |
| * Tests that trackers that don't heartbeat within a given time are considered |
| * lost. Note that this test is not a direct replacement for |
| * {@link TestLostTracker} since it doesn't test that a task |
| * running on a lost tracker is retried on another tracker. |
| */ |
| @SuppressWarnings("deprecation") |
| public class TestLostTaskTracker extends TestCase { |
| |
| private JobTracker jobTracker; |
| |
| private FakeClock clock; |
| |
| @Override |
| protected void setUp() throws Exception { |
| JobConf conf = new JobConf(); |
| conf.set(JTConfig.JT_IPC_ADDRESS, "localhost:0"); |
| conf.set(JTConfig.JT_HTTP_ADDRESS, "0.0.0.0:0"); |
| conf.setLong(JTConfig.JT_TRACKER_EXPIRY_INTERVAL, 1000); |
| clock = new FakeClock(); |
| // We use a "partial mock" of JobTracker which lets us see when certain |
| // methods are called. If we were writing JobTracker from scratch then |
| // we would make it call another object which we would mock out instead |
| // (and use a real JobTracker) so we could perform assertions on the mock. |
| // See http://mockito.googlecode.com/svn/branches/1.8.0/javadoc/org/mockito/Mockito.html#16 |
| jobTracker = spy(new JobTracker(conf, clock)); |
| } |
| |
| public void testLostTaskTrackerCalledAfterExpiryTime() throws IOException { |
| |
| String tracker1 = "tracker_tracker1:1000"; |
| String tracker2 = "tracker_tracker2:1000"; |
| |
| establishFirstContact(tracker1); |
| |
| // Wait long enough for tracker1 to be considered lost |
| // We could have used a Mockito stub here, except we don't know how many |
| // times JobTracker calls getTime() on the clock, so a static mock |
| // is appropriate. |
| clock.advance(8 * 1000); |
| |
| establishFirstContact(tracker2); |
| |
| jobTracker.checkExpiredTrackers(); |
| |
| // Now we check that JobTracker's lostTaskTracker() was called for tracker1 |
| // but not for tracker2. |
| |
| // We use an ArgumentCaptor to capture the task tracker object |
| // in the lostTaskTracker() call, so we can perform an assertion on its |
| // name. (We could also have used a custom matcher, see below.) |
| // See http://mockito.googlecode.com/svn/branches/1.8.0/javadoc/org/mockito/Mockito.html#15 |
| ArgumentCaptor<TaskTracker> argument = |
| ArgumentCaptor.forClass(TaskTracker.class); |
| |
| verify(jobTracker).lostTaskTracker(argument.capture()); |
| assertEquals(tracker1, argument.getValue().getTrackerName()); |
| |
| // Check tracker2 was not lost by using the never() construct |
| // We use a custom Hamcrest matcher to check that it was indeed tracker2 |
| // that didn't match (since tracker1 did match). |
| // See http://mockito.googlecode.com/svn/branches/1.8.0/javadoc/org/mockito/Mockito.html#3 |
| verify(jobTracker, never()).lostTaskTracker( |
| argThat(taskTrackerWithName(tracker2))); |
| } |
| |
| private Matcher<TaskTracker> taskTrackerWithName(final String name) { |
| return new ArgumentMatcher<TaskTracker>() { |
| public boolean matches(Object taskTracker) { |
| return name.equals(((TaskTracker) taskTracker).getTrackerName()); |
| } |
| }; |
| } |
| |
| private void establishFirstContact(String tracker) throws IOException { |
| TaskTrackerStatus status = new TaskTrackerStatus(tracker, |
| JobInProgress.convertTrackerNameToHostName(tracker)); |
| jobTracker.heartbeat(status, false, true, false, (short) 0); |
| } |
| |
| } |