private static String[] runTests(
      int numHosts, int slotsPerHost, int parallelism, TestLocatableInputSplit[] splits)
      throws Exception {
    AbstractJobVertex vertex = new AbstractJobVertex("test vertex");
    vertex.setParallelism(parallelism);
    vertex.setInvokableClass(DummyInvokable.class);
    vertex.setInputSplitSource(new TestInputSplitSource(splits));

    JobGraph jobGraph = new JobGraph("test job", vertex);

    ExecutionGraph eg =
        new ExecutionGraph(
            jobGraph.getJobID(), jobGraph.getName(), jobGraph.getJobConfiguration(), TIMEOUT);
    eg.setQueuedSchedulingAllowed(false);

    eg.attachJobGraph(jobGraph.getVerticesSortedTopologicallyFromSources());

    Scheduler scheduler = getScheduler(numHosts, slotsPerHost);
    eg.scheduleForExecution(scheduler);

    ExecutionVertex[] tasks = eg.getVerticesTopologically().iterator().next().getTaskVertices();
    assertEquals(parallelism, tasks.length);

    String[] hostsForTasks = new String[parallelism];
    for (int i = 0; i < parallelism; i++) {
      hostsForTasks[i] = tasks[i].getCurrentAssignedResourceLocation().getHostname();
    }

    return hostsForTasks;
  }
  @Test
  public void testMultipleInstancesPerHost() {

    TestLocatableInputSplit[] splits =
        new TestLocatableInputSplit[] {
          new TestLocatableInputSplit(1, "host1"),
          new TestLocatableInputSplit(2, "host1"),
          new TestLocatableInputSplit(3, "host2"),
          new TestLocatableInputSplit(4, "host2"),
          new TestLocatableInputSplit(5, "host3"),
          new TestLocatableInputSplit(6, "host3")
        };

    try {
      AbstractJobVertex vertex = new AbstractJobVertex("test vertex");
      vertex.setParallelism(6);
      vertex.setInvokableClass(DummyInvokable.class);
      vertex.setInputSplitSource(new TestInputSplitSource(splits));

      JobGraph jobGraph = new JobGraph("test job", vertex);

      ExecutionGraph eg =
          new ExecutionGraph(
              jobGraph.getJobID(), jobGraph.getName(), jobGraph.getJobConfiguration(), TIMEOUT);

      eg.attachJobGraph(jobGraph.getVerticesSortedTopologicallyFromSources());
      eg.setQueuedSchedulingAllowed(false);

      // create a scheduler with 6 instances where always two are on the same host
      Scheduler scheduler = new Scheduler();
      Instance i1 = getInstance(new byte[] {10, 0, 1, 1}, 12345, "host1", 1);
      Instance i2 = getInstance(new byte[] {10, 0, 1, 1}, 12346, "host1", 1);
      Instance i3 = getInstance(new byte[] {10, 0, 1, 2}, 12345, "host2", 1);
      Instance i4 = getInstance(new byte[] {10, 0, 1, 2}, 12346, "host2", 1);
      Instance i5 = getInstance(new byte[] {10, 0, 1, 3}, 12345, "host3", 1);
      Instance i6 = getInstance(new byte[] {10, 0, 1, 3}, 12346, "host4", 1);
      scheduler.newInstanceAvailable(i1);
      scheduler.newInstanceAvailable(i2);
      scheduler.newInstanceAvailable(i3);
      scheduler.newInstanceAvailable(i4);
      scheduler.newInstanceAvailable(i5);
      scheduler.newInstanceAvailable(i6);

      eg.scheduleForExecution(scheduler);

      ExecutionVertex[] tasks = eg.getVerticesTopologically().iterator().next().getTaskVertices();
      assertEquals(6, tasks.length);

      Instance taskInstance1 = tasks[0].getCurrentAssignedResource().getInstance();
      Instance taskInstance2 = tasks[1].getCurrentAssignedResource().getInstance();
      Instance taskInstance3 = tasks[2].getCurrentAssignedResource().getInstance();
      Instance taskInstance4 = tasks[3].getCurrentAssignedResource().getInstance();
      Instance taskInstance5 = tasks[4].getCurrentAssignedResource().getInstance();
      Instance taskInstance6 = tasks[5].getCurrentAssignedResource().getInstance();

      assertTrue(taskInstance1 == i1 || taskInstance1 == i2);
      assertTrue(taskInstance2 == i1 || taskInstance2 == i2);
      assertTrue(taskInstance3 == i3 || taskInstance3 == i4);
      assertTrue(taskInstance4 == i3 || taskInstance4 == i4);
      assertTrue(taskInstance5 == i5 || taskInstance5 == i6);
      assertTrue(taskInstance6 == i5 || taskInstance6 == i6);
    } catch (Exception e) {
      e.printStackTrace();
      fail(e.getMessage());
    }
  }
  /*
   * Test setup:
   * - v1 is isolated, no slot sharing
   * - v2 and v3 (not connected) share slots
   * - v4 and v5 (connected) share slots
   */
  @Test
  public void testAssignSlotSharingGroup() {
    try {
      JobVertex v1 = new JobVertex("v1");
      JobVertex v2 = new JobVertex("v2");
      JobVertex v3 = new JobVertex("v3");
      JobVertex v4 = new JobVertex("v4");
      JobVertex v5 = new JobVertex("v5");

      v1.setParallelism(4);
      v2.setParallelism(5);
      v3.setParallelism(7);
      v4.setParallelism(1);
      v5.setParallelism(11);

      v2.connectNewDataSetAsInput(v1, DistributionPattern.POINTWISE);
      v5.connectNewDataSetAsInput(v4, DistributionPattern.POINTWISE);

      SlotSharingGroup jg1 = new SlotSharingGroup();
      v2.setSlotSharingGroup(jg1);
      v3.setSlotSharingGroup(jg1);

      SlotSharingGroup jg2 = new SlotSharingGroup();
      v4.setSlotSharingGroup(jg2);
      v5.setSlotSharingGroup(jg2);

      List<JobVertex> vertices = new ArrayList<JobVertex>(Arrays.asList(v1, v2, v3, v4, v5));

      ExecutionGraph eg =
          new ExecutionGraph(
              TestingUtils.defaultExecutionContext(),
              new JobID(),
              "test job",
              new Configuration(),
              ExecutionConfigTest.getSerializedConfig(),
              AkkaUtils.getDefaultTimeout(),
              new NoRestartStrategy());
      eg.attachJobGraph(vertices);

      // verify that the vertices are all in the same slot sharing group
      SlotSharingGroup group1 = null;
      SlotSharingGroup group2 = null;

      // verify that v1 tasks have no slot sharing group
      assertNull(eg.getJobVertex(v1.getID()).getSlotSharingGroup());

      // v2 and v3 are shared
      group1 = eg.getJobVertex(v2.getID()).getSlotSharingGroup();
      assertNotNull(group1);
      assertEquals(group1, eg.getJobVertex(v3.getID()).getSlotSharingGroup());

      assertEquals(2, group1.getJobVertexIds().size());
      assertTrue(group1.getJobVertexIds().contains(v2.getID()));
      assertTrue(group1.getJobVertexIds().contains(v3.getID()));

      // v4 and v5 are shared
      group2 = eg.getJobVertex(v4.getID()).getSlotSharingGroup();
      assertNotNull(group2);
      assertEquals(group2, eg.getJobVertex(v5.getID()).getSlotSharingGroup());

      assertEquals(2, group1.getJobVertexIds().size());
      assertTrue(group2.getJobVertexIds().contains(v4.getID()));
      assertTrue(group2.getJobVertexIds().contains(v5.getID()));
    } catch (Exception e) {
      e.printStackTrace();
      fail(e.getMessage());
    }
  }