@Test
  public void testAssignMigrations() {
    servers.clear();
    servers.put(
        new TServerInstance(HostAndPort.fromParts("127.0.0.1", 1234), "a"), new FakeTServer());
    servers.put(
        new TServerInstance(HostAndPort.fromParts("127.0.0.1", 1235), "b"), new FakeTServer());
    servers.put(
        new TServerInstance(HostAndPort.fromParts("127.0.0.1", 1236), "c"), new FakeTServer());
    List<KeyExtent> metadataTable = new ArrayList<KeyExtent>();
    String table = "t1";
    metadataTable.add(makeExtent(table, null, null));
    table = "t2";
    metadataTable.add(makeExtent(table, "a", null));
    metadataTable.add(makeExtent(table, null, "a"));
    table = "t3";
    metadataTable.add(makeExtent(table, "a", null));
    metadataTable.add(makeExtent(table, "b", "a"));
    metadataTable.add(makeExtent(table, "c", "b"));
    metadataTable.add(makeExtent(table, "d", "c"));
    metadataTable.add(makeExtent(table, "e", "d"));
    metadataTable.add(makeExtent(table, null, "e"));
    Collections.sort(metadataTable);

    TestDefaultLoadBalancer balancer = new TestDefaultLoadBalancer();

    SortedMap<TServerInstance, TabletServerStatus> current =
        new TreeMap<TServerInstance, TabletServerStatus>();
    for (Entry<TServerInstance, FakeTServer> entry : servers.entrySet()) {
      current.put(entry.getKey(), entry.getValue().getStatus(entry.getKey()));
    }
    assignTablets(metadataTable, servers, current, balancer);

    // Verify that the counts on the tables are correct
    Map<String, Integer> expectedCounts = new HashMap<String, Integer>();
    expectedCounts.put("t1", 1);
    expectedCounts.put("t2", 1);
    expectedCounts.put("t3", 2);
    checkBalance(metadataTable, servers, expectedCounts);

    // Rebalance once
    for (Entry<TServerInstance, FakeTServer> entry : servers.entrySet()) {
      current.put(entry.getKey(), entry.getValue().getStatus(entry.getKey()));
    }

    // Nothing should happen, we are balanced
    ArrayList<TabletMigration> out = new ArrayList<TabletMigration>();
    balancer.getMigrations(current, out);
    assertEquals(out.size(), 0);

    // Take down a tabletServer
    TServerInstance first = current.keySet().iterator().next();
    current.remove(first);
    FakeTServer remove = servers.remove(first);

    // reassign offline extents
    assignTablets(remove.extents, servers, current, balancer);
    checkBalance(metadataTable, servers, null);
  }
  @Test
  public void testUnevenAssignment2() {
    servers.clear();
    // make 26 servers
    for (char c : "abcdefghijklmnopqrstuvwxyz".toCharArray()) {
      String cString = Character.toString(c);
      HostAndPort fakeAddress = HostAndPort.fromParts("127.0.0.1", (int) c);
      String fakeInstance = cString;
      TServerInstance tsi = new TServerInstance(fakeAddress, fakeInstance);
      FakeTServer fakeTServer = new FakeTServer();
      servers.put(tsi, fakeTServer);
    }
    // put 60 tablets on 25 of them
    List<Entry<TServerInstance, FakeTServer>> shortList =
        new ArrayList<Entry<TServerInstance, FakeTServer>>(servers.entrySet());
    Entry<TServerInstance, FakeTServer> shortServer = shortList.remove(0);
    int c = 0;
    for (int i = 0; i < 60; i++) {
      for (Entry<TServerInstance, FakeTServer> entry : shortList) {
        entry.getValue().extents.add(makeExtent("t" + c, null, null));
      }
    }
    // put 10 on the that short server:
    for (int i = 0; i < 10; i++) {
      shortServer.getValue().extents.add(makeExtent("s" + i, null, null));
    }

    TestDefaultLoadBalancer balancer = new TestDefaultLoadBalancer();
    Set<KeyExtent> migrations = Collections.emptySet();
    int moved = 0;
    // balance until we can't balance no more!
    while (true) {
      List<TabletMigration> migrationsOut = new ArrayList<TabletMigration>();
      balancer.balance(getAssignments(servers), migrations, migrationsOut);
      if (migrationsOut.size() == 0) break;
      for (TabletMigration migration : migrationsOut) {
        if (servers.get(migration.oldServer).extents.remove(migration.tablet)) moved++;
        servers.get(migration.newServer).extents.add(migration.tablet);
      }
    }
    // average is 58, with 2 at 59: we need 48 more moved to the short server
    assertEquals(48, moved);
  }
 private void assignTablets(
     List<KeyExtent> metadataTable,
     Map<TServerInstance, FakeTServer> servers,
     SortedMap<TServerInstance, TabletServerStatus> status,
     TestDefaultLoadBalancer balancer) {
   // Assign tablets
   for (KeyExtent extent : metadataTable) {
     TServerInstance assignment = balancer.getAssignment(status, extent, null);
     assertNotNull(assignment);
     assertFalse(servers.get(assignment).extents.contains(extent));
     servers.get(assignment).extents.add(extent);
   }
 }
 @Test
 public void testUnevenAssignment() {
   servers.clear();
   for (char c : "abcdefghijklmnopqrstuvwxyz".toCharArray()) {
     String cString = Character.toString(c);
     HostAndPort fakeAddress = HostAndPort.fromParts("127.0.0.1", (int) c);
     String fakeInstance = cString;
     TServerInstance tsi = new TServerInstance(fakeAddress, fakeInstance);
     FakeTServer fakeTServer = new FakeTServer();
     servers.put(tsi, fakeTServer);
     fakeTServer.extents.add(makeExtent(cString, null, null));
   }
   // Put more tablets on one server, but not more than the number of servers
   Entry<TServerInstance, FakeTServer> first = servers.entrySet().iterator().next();
   first.getValue().extents.add(makeExtent("newTable", "a", null));
   first.getValue().extents.add(makeExtent("newTable", "b", "a"));
   first.getValue().extents.add(makeExtent("newTable", "c", "b"));
   first.getValue().extents.add(makeExtent("newTable", "d", "c"));
   first.getValue().extents.add(makeExtent("newTable", "e", "d"));
   first.getValue().extents.add(makeExtent("newTable", "f", "e"));
   first.getValue().extents.add(makeExtent("newTable", "g", "f"));
   first.getValue().extents.add(makeExtent("newTable", "h", "g"));
   first.getValue().extents.add(makeExtent("newTable", "i", null));
   TestDefaultLoadBalancer balancer = new TestDefaultLoadBalancer();
   Set<KeyExtent> migrations = Collections.emptySet();
   int moved = 0;
   // balance until we can't balance no more!
   while (true) {
     List<TabletMigration> migrationsOut = new ArrayList<TabletMigration>();
     balancer.balance(getAssignments(servers), migrations, migrationsOut);
     if (migrationsOut.size() == 0) break;
     for (TabletMigration migration : migrationsOut) {
       if (servers.get(migration.oldServer).extents.remove(migration.tablet)) moved++;
       servers.get(migration.newServer).extents.add(migration.tablet);
     }
   }
   assertEquals(8, moved);
 }