io.github.retz.scheduler.RetzSchedulerTest.java Source code

Java tutorial

Introduction

Here is the source code for io.github.retz.scheduler.RetzSchedulerTest.java

Source

/**
 *    Retz
 *    Copyright (C) 2016 Nautilus Technologies, Inc.
 *
 *    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 io.github.retz.scheduler;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import io.github.retz.db.Database;
import io.github.retz.protocol.data.*;
import org.apache.mesos.Protos;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Optional;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

public class RetzSchedulerTest {

    MesosSchedulerDummyDriver driver;
    RetzScheduler scheduler;
    ObjectMapper mapper;

    @Before
    public void before() throws Exception {
        mapper = new ObjectMapper();
        mapper.registerModule(new Jdk8Module());

        Protos.FrameworkInfo frameworkInfo = Protos.FrameworkInfo.newBuilder().setUser("")
                .setName(RetzScheduler.FRAMEWORK_NAME).build();

        InputStream in = Launcher.class.getResourceAsStream("/retz.properties");
        Launcher.Configuration conf = new Launcher.Configuration(new ServerConfiguration(in));

        Database.getInstance().init(conf.getServerConfig());
        scheduler = new RetzScheduler(conf, frameworkInfo);
        driver = new MesosSchedulerDummyDriver(scheduler, frameworkInfo, conf.getMesosMaster());
    }

    @After
    public void after() {
        driver.clear();
        Database.getInstance().clear();
        Database.getInstance().stop();
    }

    @Test
    public void justRun() {
        driver.start();
        driver.stop();
        driver.run();
    }

    // @Test
    public void decline() {
        driver.start();
        String offerId = "super duper blooper";

        Protos.Offer offers[] = { buildOffer(offerId, 4, 512) };

        driver.clear();
        driver.dummyOffer(Arrays.asList(offers));
        assertThat(driver.getDeclined().size(), is(1));
        assertThat(driver.getDeclined().get(0).getValue(), is(offerId));

        driver.stop();
    }

    //TODO: @Test
    public void launch() throws InterruptedException, JsonProcessingException, IOException {
        String files[] = { "http://foobar.boom.co.jp/foo.tar.gz" };
        Applications.load(new Application("fooapp", new LinkedList<String>(), new LinkedList<String>(),
                Arrays.asList(files), Optional.empty(), Optional.empty(), "deadbeef", new MesosContainer(), true));
        Job job = new Job("fooapp", "foocmd", null, 2, 256);
        JobQueue.push(job);

        driver.start();
        String offerId = "super duper blooper";

        Protos.Offer offers[] = { buildOffer(offerId, 4, 512) };

        driver.clear();
        driver.dummyOffer(Arrays.asList(offers));

        assertTrue(driver.getDeclined().isEmpty());
        assertThat(driver.getAccepted().size(), is(1));
        assertThat(driver.getTasks().size(), is(1));

        Protos.TaskInfo task = driver.getTasks().get(0);

        assertThat(mapper.readValue(task.getData().toStringUtf8(), Job.class).cmd(), is(job.cmd()));
        assertThat(task.getSlaveId().getValue(), is(offers[0].getSlaveId().getValue()));
        assertFalse(task.getTaskId().getValue().isEmpty());
        // TODO: Not knowing why this is empty
        for (Protos.Resource r : task.getExecutor().getResourcesList()) {
            System.err.println(r.getName());
            System.err.println(r.getScalar().getValue());
        }

        assertThat(JobQueue.countRunning(), is(1));
        driver.dummyTaskStarted();
        assertThat(JobQueue.countRunning(), is(1));

        // TODO: introduce DI to skip URL fetch
        //driver.dummyTaskFinish();
        //assertTrue(scheduler.getRunning().isEmpty());

        Applications.unload("fooapp");
        driver.stop();
    }

    @Test
    public void notEnough() throws Exception {
        String files[] = { "http://foobar.boom.co.jp/foo.tar.gz" };
        Database.getInstance().addUser(new User("Deadbeef", "cafebabe", true));
        Applications.load(new Application("fooapp", new LinkedList<String>(), new LinkedList<String>(),
                Arrays.asList(files), Optional.empty(), Optional.empty(), "Deadbeef", new MesosContainer(), true));
        Job job = new Job("fooapp", "foocmd", null, 2, 256);
        JobQueue.push(job);

        driver.start();
        String offerId = "super duper blooper";

        Protos.Offer offers[] = { buildOffer(offerId, 2, 34) };

        driver.clear();
        driver.dummyOffer(Arrays.asList(offers));

        try {
            // Now database update is async with Stanchion, just waiting
            Thread.sleep(5000);
        } catch (InterruptedException e) {
        }

        assertThat(driver.getDeclined().size(), is(1));
        assertTrue(driver.getAccepted().isEmpty());
        assertTrue(driver.getTasks().isEmpty());

        Applications.unload("fooapp");
        driver.stop();
    }

    // TODO: @Test
    public void slaveFail() throws InterruptedException, JsonProcessingException, IOException {
        String files[] = { "http://foobar.boom.co.jp/foo.tar.gz" };
        Applications.load(new Application("fooapp", new LinkedList<String>(), new LinkedList<String>(),
                Arrays.asList(files), Optional.empty(), Optional.empty(), "Deadbeef", new MesosContainer(), true));
        Job job = new Job("fooapp", "foocmd", null, 2, 256);
        JobQueue.push(job);

        driver.start();
        String offerId = "super duper blooper";

        Protos.Offer offers[] = { buildOffer(offerId, 4, 512) };
        Protos.SlaveID slaveID = offers[0].getSlaveId();

        driver.clear();
        driver.dummyOffer(Arrays.asList(offers));

        assertTrue(driver.getDeclined().isEmpty());
        assertThat(driver.getAccepted().size(), is(1));
        assertThat(driver.getTasks().size(), is(1));

        Protos.TaskInfo task = driver.getTasks().get(0);
        assertThat(mapper.readValue(task.getData().toStringUtf8(), Job.class).cmd(), is(job.cmd()));
        assertThat(task.getSlaveId().getValue(), is(slaveID.getValue()));
        assertFalse(task.getTaskId().getValue().isEmpty());
        // TODO: Not knowing why this is empty
        for (Protos.Resource r : task.getExecutor().getResourcesList()) {
            System.err.println(r.getName());
            System.err.println(r.getScalar().getValue());
        }

        assertThat(JobQueue.countRunning(), is(1));
        driver.dummyTaskStarted();
        assertThat(JobQueue.countRunning(), is(1));

        // Simulate slave failure to test task re-assign
        scheduler.slaveLost(driver, slaveID);
        assertThat(JobQueue.countRunning(), is(0));

        // TODO: introduce
        //driver.dummyTaskFinish();
        //assertTrue(scheduler.getRunning().isEmpty());

        Applications.unload("fooapp");
        driver.stop();
    }

    private Protos.Offer buildOffer(String offerId, int cpus, int mem) {
        return RetzSchedulerTest.buildOffer(driver.frameworkInfo.getId(), 0, offerId, cpus, mem);
    }

    static Protos.Offer buildOffer(Protos.FrameworkID fid, int slaveNo, String offerId, int cpus, int mem) {

        String hostname = "127.0.0." + slaveNo + ":5051";
        String slaveId = "slave(" + slaveNo + ")@" + hostname;

        Protos.Offer.Builder builder = Protos.Offer.newBuilder()
                .addAllResources(ResourceConstructor.construct(cpus, mem))
                .setSlaveId(Protos.SlaveID.newBuilder().setValue(slaveId).build()).setFrameworkId(fid)
                .setHostname(hostname).setId(Protos.OfferID.newBuilder().setValue(offerId).build());
        return builder.build();
    }

    public static Protos.Offer buildOffer(String fid, String sid, String offerId, int cpus, int mem) {
        Protos.Offer.Builder builder = Protos.Offer.newBuilder()
                .addAllResources(ResourceConstructor.construct(cpus, mem))
                .setSlaveId(Protos.SlaveID.newBuilder().setValue(sid).build())
                .setFrameworkId(Protos.FrameworkID.newBuilder().setValue(fid).build()).setHostname("127.0.0.1:5051")
                .setId(Protos.OfferID.newBuilder().setValue(offerId).build());
        return builder.build();
    }
}