@Test
  public void testLifecycleUnknown() throws Exception {
    initializeOneAgent();

    Request request =
        Request.Builder.preparePut()
            .setUri(
                coordinatorUriBuilder()
                    .appendPath("/v1/slot/lifecycle")
                    .addParameter("binary", "apple:*")
                    .build())
            .setBodyGenerator(createStaticBodyGenerator("unknown", UTF_8))
            .build();
    StatusResponse response = httpClient.execute(request, createStatusResponseHandler());

    AgentStatus agentStatus = coordinator.getAgentByAgentId(agentId);
    SlotStatus apple1Status = agentStatus.getSlotStatus(apple1SotId);
    SlotStatus apple2Status = agentStatus.getSlotStatus(apple2SlotId);
    SlotStatus bananaStatus = agentStatus.getSlotStatus(bananaSlotId);

    assertEquals(response.getStatusCode(), Status.BAD_REQUEST.getStatusCode());
    assertEquals(apple1Status.getState(), STOPPED);
    assertEquals(apple2Status.getState(), STOPPED);
    assertEquals(bananaStatus.getState(), STOPPED);
  }
  @Test
  public void testKill() throws Exception {
    initializeOneAgent();

    coordinator.setState(RUNNING, Predicates.<SlotStatus>alwaysTrue(), null);

    Request request =
        Request.Builder.preparePut()
            .setUri(
                coordinatorUriBuilder()
                    .appendPath("/v1/slot/lifecycle")
                    .addParameter("binary", "apple:*")
                    .build())
            .setBodyGenerator(createStaticBodyGenerator("killing", UTF_8))
            .build();
    List<SlotStatusRepresentation> actual =
        httpClient.execute(
            request, createJsonResponseHandler(slotStatusesCodec, Status.OK.getStatusCode()));

    AgentStatus agentStatus = coordinator.getAgentByAgentId(agentId);
    SlotStatus apple1Status = agentStatus.getSlotStatus(apple1SotId);
    SlotStatus apple2Status = agentStatus.getSlotStatus(apple2SlotId);
    SlotStatus bananaStatus = agentStatus.getSlotStatus(bananaSlotId);

    List<SlotStatusRepresentation> expected =
        ImmutableList.of(
            slotStatusRepresentationFactory.create(apple1Status),
            slotStatusRepresentationFactory.create(apple2Status));

    assertEqualsNoOrder(actual, expected);
    assertEquals(apple1Status.getState(), STOPPED);
    assertEquals(apple2Status.getState(), STOPPED);
    assertEquals(bananaStatus.getState(), RUNNING);
  }
  @Test
  public void testTerminate() throws Exception {
    initializeOneAgent();

    AgentStatus agentStatus = coordinator.getAgentByAgentId(agentId);
    SlotStatus apple1Status = agentStatus.getSlotStatus(apple1SotId);
    SlotStatus apple2Status = agentStatus.getSlotStatus(apple2SlotId);

    Request request =
        Request.Builder.prepareDelete()
            .setUri(
                coordinatorUriBuilder()
                    .appendPath("/v1/slot")
                    .addParameter("host", "apple*")
                    .build())
            .build();
    List<SlotStatusRepresentation> actual =
        httpClient.execute(
            request, createJsonResponseHandler(slotStatusesCodec, Status.OK.getStatusCode()));

    apple1Status = apple1Status.changeState(TERMINATED);
    apple2Status = apple2Status.changeState(TERMINATED);
    SlotStatus bananaStatus = coordinator.getAgentByAgentId(agentId).getSlotStatus(bananaSlotId);

    List<SlotStatusRepresentation> expected =
        ImmutableList.of(
            slotStatusRepresentationFactory.create(apple1Status),
            slotStatusRepresentationFactory.create(apple2Status.changeState(TERMINATED)));

    assertEqualsNoOrder(actual, expected);

    assertEquals(apple1Status.getState(), TERMINATED);
    assertEquals(apple2Status.getState(), TERMINATED);
    assertEquals(bananaStatus.getState(), STOPPED);
  }
  private void assertOkResponse(Response response, SlotLifecycleState state, UUID... slotIds) {
    assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());

    AgentStatus agentStatus = coordinator.getAgentByAgentId(agentId);
    Builder<SlotStatusRepresentation> builder = ImmutableList.builder();
    for (UUID slotId : slotIds) {
      SlotStatus slotStatus = agentStatus.getSlotStatus(slotId);
      builder.add(
          SlotStatusRepresentation.from(slotStatus.changeState(state), prefixSize, MOCK_REPO));
      assertEquals(slotStatus.getAssignment(), APPLE_ASSIGNMENT);
    }
    assertEqualsNoOrder((Collection<?>) response.getEntity(), builder.build());
    assertNull(
        response
            .getMetadata()
            .get("Content-Type")); // content type is set by jersey based on @Produces
  }
  @Test
  public void testUpgrade() throws Exception {
    initializeOneAgent();

    UpgradeVersions upgradeVersions = new UpgradeVersions("2.0", "2.0");
    Request request =
        Request.Builder.preparePost()
            .setUri(
                coordinatorUriBuilder()
                    .appendPath("/v1/slot/assignment")
                    .addParameter("host", "apple*")
                    .build())
            .setHeader(CONTENT_TYPE, APPLICATION_JSON)
            .setBodyGenerator(jsonBodyGenerator(upgradeVersionsCodec, upgradeVersions))
            .build();
    List<SlotStatusRepresentation> actual =
        httpClient.execute(
            request, createJsonResponseHandler(slotStatusesCodec, Status.OK.getStatusCode()));

    AgentStatus agentStatus = coordinator.getAgentByAgentId(agentId);
    SlotStatus apple1Status = agentStatus.getSlotStatus(apple1SotId);
    SlotStatus apple2Status = agentStatus.getSlotStatus(apple2SlotId);
    SlotStatus bananaStatus = agentStatus.getSlotStatus(bananaSlotId);

    List<SlotStatusRepresentation> expected =
        ImmutableList.of(
            slotStatusRepresentationFactory.create(apple1Status),
            slotStatusRepresentationFactory.create(apple2Status));

    assertEqualsNoOrder(actual, expected);

    assertEquals(apple1Status.getState(), STOPPED);
    assertEquals(apple2Status.getState(), STOPPED);
    assertEquals(bananaStatus.getState(), STOPPED);

    assertEquals(
        apple1Status.getAssignment(),
        upgradeVersions.upgradeAssignment(MOCK_REPO, APPLE_ASSIGNMENT));
    assertEquals(
        apple2Status.getAssignment(),
        upgradeVersions.upgradeAssignment(MOCK_REPO, APPLE_ASSIGNMENT));
    assertEquals(bananaStatus.getAssignment(), BANANA_ASSIGNMENT);
  }
  @Test
  public void testGetAllSlots() throws Exception {
    initializeOneAgent();

    Request request =
        Request.Builder.prepareGet()
            .setUri(
                coordinatorUriBuilder().appendPath("/v1/slot").addParameter("name", "*").build())
            .build();
    List<SlotStatusRepresentation> actual =
        httpClient.execute(
            request, createJsonResponseHandler(slotStatusesCodec, Status.OK.getStatusCode()));

    AgentStatus agentStatus = coordinator.getAgentByAgentId(agentId);

    int prefixSize =
        shortestUniquePrefix(
            asList(
                agentStatus.getSlotStatus(apple1SotId).getId().toString(),
                agentStatus.getSlotStatus(apple2SlotId).getId().toString(),
                agentStatus.getSlotStatus(bananaSlotId).getId().toString()),
            MIN_PREFIX_SIZE);

    assertEqualsNoOrder(
        actual,
        ImmutableList.of(
            SlotStatusRepresentation.from(
                agentStatus.getSlotStatus(apple1SotId), prefixSize, MOCK_REPO),
            SlotStatusRepresentation.from(
                agentStatus.getSlotStatus(apple2SlotId), prefixSize, MOCK_REPO),
            SlotStatusRepresentation.from(
                agentStatus.getSlotStatus(bananaSlotId), prefixSize, MOCK_REPO)));
  }
  @Test
  public void testAgentProvision() throws Exception {
    // provision the agent and verify
    String instanceType = "instance-type";
    AgentProvisioningRepresentation agentProvisioningRepresentation =
        new AgentProvisioningRepresentation(
            "agent:config:1", 1, instanceType, null, null, null, null, null);
    Request request =
        Request.Builder.preparePost()
            .setUri(coordinatorUriBuilder().appendPath("/v1/admin/agent").build())
            .setHeader(CONTENT_TYPE, APPLICATION_JSON)
            .setBodyGenerator(
                jsonBodyGenerator(agentProvisioningCodec, agentProvisioningRepresentation))
            .build();
    List<AgentStatusRepresentation> agents =
        httpClient.execute(
            request, createJsonResponseHandler(agentStatusesCodec, Status.OK.getStatusCode()));

    assertEquals(agents.size(), 1);
    String instanceId = agents.get(0).getInstanceId();
    assertNotNull(instanceId);
    String location = agents.get(0).getLocation();
    assertNotNull(location);
    assertEquals(agents.get(0).getInstanceType(), instanceType);
    assertNull(agents.get(0).getAgentId());
    assertNull(agents.get(0).getSelf());
    assertNull(agents.get(0).getExternalUri());
    assertEquals(agents.get(0).getState(), AgentLifecycleState.PROVISIONING);

    // start the agent and verify
    AgentStatus expectedAgentStatus = provisioner.startAgent(instanceId);
    coordinator.updateAllAgentsAndWait();
    assertEquals(coordinator.getAgents().size(), 1);
    assertEquals(coordinator.getAgent(instanceId).getInstanceId(), instanceId);
    assertEquals(coordinator.getAgent(instanceId).getInstanceType(), instanceType);
    assertEquals(coordinator.getAgent(instanceId).getLocation(), location);
    assertEquals(coordinator.getAgent(instanceId).getAgentId(), expectedAgentStatus.getAgentId());
    assertEquals(
        coordinator.getAgent(instanceId).getInternalUri(), expectedAgentStatus.getInternalUri());
    assertEquals(
        coordinator.getAgent(instanceId).getExternalUri(), expectedAgentStatus.getExternalUri());
    assertEquals(coordinator.getAgent(instanceId).getState(), AgentLifecycleState.ONLINE);

    request =
        Request.Builder.prepareGet()
            .setUri(coordinatorUriBuilder().appendPath("/v1/admin/agent").build())
            .build();

    agents =
        httpClient.execute(
            request, createJsonResponseHandler(agentStatusesCodec, Status.OK.getStatusCode()));
    assertEquals(agents.size(), 1);

    AgentStatusRepresentation actual = agents.get(0);
    assertEquals(actual.getInstanceId(), instanceId);
    assertEquals(actual.getInstanceType(), instanceType);
    assertEquals(actual.getLocation(), location);
    assertEquals(actual.getAgentId(), expectedAgentStatus.getAgentId());
    assertEquals(actual.getSelf(), expectedAgentStatus.getInternalUri());
    assertEquals(actual.getExternalUri(), expectedAgentStatus.getExternalUri());
    assertEquals(actual.getState(), AgentLifecycleState.ONLINE);
  }