// Copyright 2016 Twitter. All rights reserved.
//
// 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 com.twitter.heron.scheduler.yarn;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import org.apache.reef.client.ClientConfiguration;
import org.apache.reef.client.DriverConfiguration;
import org.apache.reef.client.REEF;
import org.apache.reef.client.RunningJob;
import org.apache.reef.driver.context.ActiveContext;
import org.apache.reef.driver.evaluator.AllocatedEvaluator;
import org.apache.reef.driver.evaluator.EvaluatorRequestor;
import org.apache.reef.runtime.local.client.LocalRuntimeConfiguration;
import org.apache.reef.tang.Configuration;
import org.apache.reef.tang.Injector;
import org.apache.reef.tang.Tang;
import org.apache.reef.tang.annotations.Unit;
import org.apache.reef.wake.EventHandler;
import org.apache.reef.wake.time.event.StartTime;
import org.junit.Test;
import com.twitter.heron.scheduler.yarn.DriverOnLocalReefTest.TestDriver.Activated;
import com.twitter.heron.scheduler.yarn.DriverOnLocalReefTest.TestDriver.Allocated;
import com.twitter.heron.scheduler.yarn.DriverOnLocalReefTest.TestDriver.DriverStarter;
import com.twitter.heron.spi.packing.PackingPlan;
import com.twitter.heron.spi.packing.Resource;
public class DriverOnLocalReefTest {
@Test
public void requestContainersForTMasterAndWorkers() throws Exception {
Configuration runtimeConf = LocalRuntimeConfiguration.CONF.build();
Configuration reefClientConf = ClientConfiguration.CONF
.set(ClientConfiguration.ON_JOB_RUNNING, ClientListener.JobRunning.class)
.build();
Configuration driverConf = DriverConfiguration.CONF
.set(DriverConfiguration.ON_DRIVER_STARTED, DriverStarter.class)
.set(DriverConfiguration.ON_EVALUATOR_ALLOCATED, Allocated.class)
.set(DriverConfiguration.ON_CONTEXT_ACTIVE, Activated.class)
.build();
final Injector injector = Tang.Factory.getTang().newInjector(runtimeConf, reefClientConf);
final REEF reef = injector.getInstance(REEF.class);
final ClientListener clientListener = injector.getInstance(ClientListener.class);
clientListener.jobWatcher = new CountDownLatch(1);
reef.submit(driverConf);
clientListener.jobWatcher.await(1, TimeUnit.SECONDS);
// The local implementation can fail to find JAVA_HOME. It can cause this test to fail.
// Uncomment the verification steps below to test it manually
// Assert.assertEquals(0, clientListener.jobWatcher.getCount());
}
@Unit
static class ClientListener {
private CountDownLatch jobWatcher = new CountDownLatch(1);
@Inject
ClientListener() {
}
class JobRunning implements EventHandler<RunningJob> {
@Override
public void onNext(RunningJob runningJob) {
System.out.println("job is running");
jobWatcher.countDown();
}
}
}
@Unit
static class TestDriver {
private HeronMasterDriver driver;
private CountDownLatch counter;
@Inject
TestDriver(EvaluatorRequestor requestor) throws IOException {
driver = new HeronMasterDriver(requestor, null, "", "", "", "", null, null, null, 0, false);
}
private void addContainer(int id,
double cpu,
long mem,
Set<PackingPlan.ContainerPlan> containers) {
Resource resource = new Resource(cpu, mem * 1024 * 1024, 0L);
PackingPlan.ContainerPlan container = new PackingPlan.ContainerPlan(id, null, resource);
containers.add(container);
}
class DriverStarter implements EventHandler<StartTime> {
@Override
public void onNext(StartTime startTime) {
try {
counter = new CountDownLatch(2);
driver.scheduleTMasterContainer();
Set<PackingPlan.ContainerPlan> containers = new HashSet<>();
addContainer(1, 1.0, 512L, containers);
PackingPlan packing = new PackingPlan("packingId", containers);
driver.scheduleHeronWorkers(packing);
counter.await(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (HeronMasterDriver.ContainerAllocationException e) {
throw new RuntimeException(e);
}
}
}
class Allocated implements EventHandler<AllocatedEvaluator> {
@Override
public void onNext(AllocatedEvaluator evaluator) {
driver.new ContainerAllocationHandler().onNext(evaluator);
}
}
class Activated implements EventHandler<ActiveContext> {
@Override
public void onNext(ActiveContext activeContext) {
counter.countDown();
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
activeContext.close();
}
}
}
}