/**
* Licensed 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.aurora.scheduler.preemptor;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSetMultimap;
import org.apache.aurora.gen.AssignedTask;
import org.apache.aurora.gen.JobKey;
import org.apache.aurora.gen.ScheduleStatus;
import org.apache.aurora.gen.ScheduledTask;
import org.apache.aurora.gen.TaskConfig;
import org.apache.aurora.scheduler.events.PubsubEvent.TaskStateChange;
import org.apache.aurora.scheduler.storage.entities.IAssignedTask;
import org.apache.aurora.scheduler.storage.entities.IScheduledTask;
import org.junit.Before;
import org.junit.Test;
import static org.apache.aurora.gen.ScheduleStatus.ASSIGNED;
import static org.apache.aurora.gen.ScheduleStatus.FAILED;
import static org.apache.aurora.gen.ScheduleStatus.FINISHED;
import static org.apache.aurora.gen.ScheduleStatus.KILLED;
import static org.apache.aurora.gen.ScheduleStatus.KILLING;
import static org.apache.aurora.gen.ScheduleStatus.PENDING;
import static org.apache.aurora.gen.ScheduleStatus.RUNNING;
import static org.apache.aurora.gen.ScheduleStatus.THROTTLED;
import static org.junit.Assert.assertEquals;
public class ClusterStateImplTest {
private ClusterStateImpl state;
@Before
public void setUp() {
state = new ClusterStateImpl();
}
@Test(expected = UnsupportedOperationException.class)
public void testImmutable() {
state.getSlavesToActiveTasks().clear();
}
@Test
public void testTaskLifecycle() {
IAssignedTask a = makeTask("a", "s1");
assertVictims();
changeState(a, THROTTLED);
assertVictims();
changeState(a, PENDING);
assertVictims();
changeState(a, ASSIGNED);
assertVictims(a);
changeState(a, RUNNING);
assertVictims(a);
changeState(a, KILLING);
assertVictims(a);
changeState(a, FINISHED);
assertVictims();
}
@Test
public void testTaskChangesSlaves() {
// We do not intend to handle the case of an external failure leading to the same task ID
// on a different slave.
IAssignedTask a = makeTask("a", "s1");
IAssignedTask a1 = makeTask("a", "s2");
changeState(a, RUNNING);
changeState(a1, RUNNING);
assertVictims(a, a1);
}
@Test
public void testMultipleTasks() {
IAssignedTask a = makeTask("a", "s1");
IAssignedTask b = makeTask("b", "s1");
IAssignedTask c = makeTask("c", "s2");
IAssignedTask d = makeTask("d", "s3");
IAssignedTask e = makeTask("e", "s3");
IAssignedTask f = makeTask("f", "s1");
changeState(a, RUNNING);
assertVictims(a);
changeState(b, RUNNING);
assertVictims(a, b);
changeState(c, RUNNING);
assertVictims(a, b, c);
changeState(d, RUNNING);
assertVictims(a, b, c, d);
changeState(e, RUNNING);
assertVictims(a, b, c, d, e);
changeState(c, FINISHED);
assertVictims(a, b, d, e);
changeState(a, FAILED);
changeState(e, KILLED);
assertVictims(b, d);
changeState(f, RUNNING);
assertVictims(b, d, f);
}
private void assertVictims(IAssignedTask... tasks) {
ImmutableMultimap.Builder<String, PreemptionVictim> victims = ImmutableSetMultimap.builder();
for (IAssignedTask task : tasks) {
victims.put(task.getSlaveId(), PreemptionVictim.fromTask(task));
}
assertEquals(victims.build(), state.getSlavesToActiveTasks());
}
private IAssignedTask makeTask(String taskId, String slaveId) {
return IAssignedTask.build(new AssignedTask()
.setTaskId(taskId)
.setSlaveId(slaveId)
.setSlaveHost(slaveId + "host")
.setTask(new TaskConfig().setJob(new JobKey("role", "env", "job"))));
}
private void changeState(IAssignedTask assignedTask, ScheduleStatus status) {
IScheduledTask task = IScheduledTask.build(new ScheduledTask()
.setStatus(status)
.setAssignedTask(assignedTask.newBuilder()));
state.taskChangedState(TaskStateChange.transition(task, ScheduleStatus.INIT));
}
}