@Test
  public void testHints_hintOnApplicationTemplate() throws Exception {

    TestApplication app1 = new TestApplication();
    app1.name("app1");
    TestApplication app2 = new TestApplication();
    app2.name("app2");
    Application app3 = new Application("app3", new ApplicationTemplate("tpl").qualifier("v1"));

    String t1 =
        this.mngr.createTarget(
            "id: t1\nprop: ok\nname: target 1\ndescription: t1's target\nhandler: h");
    String t2 = this.mngr.createTarget("id: t2\nprop: ok\nhandler: docker");

    // Hint between app1 and app2's template and t1.
    // t1 has now a scope, which includes (indirectly) app1 and app2.
    // Therefore, t1 should not be listed for app3 (not in the scope).
    this.mngr.addHint(t1, app1.getTemplate());

    List<TargetWrapperDescriptor> beans = this.mngr.listPossibleTargets(app1);
    Assert.assertEquals(2, beans.size());

    TargetWrapperDescriptor b1 = beans.get(0);
    Assert.assertEquals(t1, b1.getId());
    Assert.assertEquals("target 1", b1.getName());
    Assert.assertEquals("t1's target", b1.getDescription());
    Assert.assertNotNull(b1.getHandler());
    Assert.assertFalse(b1.isDefault());

    TargetWrapperDescriptor b2 = beans.get(1);
    Assert.assertEquals(t2, b2.getId());
    Assert.assertEquals("docker", b2.getHandler());
    Assert.assertNull(b2.getName());
    Assert.assertNull(b2.getDescription());
    Assert.assertFalse(b2.isDefault());

    List<TargetWrapperDescriptor> otherBeans = this.mngr.listPossibleTargets(app2);
    Assert.assertEquals(beans, otherBeans);

    otherBeans = this.mngr.listPossibleTargets(app2.getTemplate());
    Assert.assertEquals(beans, otherBeans);

    beans = this.mngr.listPossibleTargets(app3);
    Assert.assertEquals(1, beans.size());

    b2 = beans.get(0);
    Assert.assertEquals(t2, b2.getId());
    Assert.assertEquals("docker", b2.getHandler());
    Assert.assertNull(b2.getName());
    Assert.assertNull(b2.getDescription());
    Assert.assertFalse(b2.isDefault());
  }
  @Test
  public void testCopyOriginalMapping_withException() throws Exception {

    // Check that when the association fails for one instance,
    // it does not prevent others from being processed.

    TestApplication app = new TestApplication();
    String instancePath = InstanceHelpers.computeInstancePath(app.getMySqlVm());
    String tomcatPath = InstanceHelpers.computeInstancePath(app.getTomcatVm());

    String t1 = this.mngr.createTarget("prop: ok\nid: t1\nhandler: h");
    String t2 = this.mngr.createTarget("prop: ok\nid: t2\nhandler: h");

    // Association is on the template
    Assert.assertNull(this.mngr.findTargetId(app, instancePath));
    this.mngr.associateTargetWith(t1, app.getTemplate(), instancePath);
    this.mngr.associateTargetWith(t1, app.getTemplate(), tomcatPath);

    // Set a new default for the application
    this.mngr.associateTargetWith(t2, app, null);
    Assert.assertEquals(t2, this.mngr.findTargetId(app, instancePath));
    Assert.assertEquals(t2, this.mngr.findTargetId(app, tomcatPath));

    // Change the state
    app.getMySqlVm().setStatus(InstanceStatus.DEPLOYED_STARTED);

    // The mapping won't be overwritten for the running instance
    this.mngr.copyOriginalMapping(app);
    Assert.assertEquals(t2, this.mngr.findTargetId(app, instancePath));
    Assert.assertEquals(t1, this.mngr.findTargetId(app, tomcatPath));
  }
  @Test
  public void testCopyOriginalMapping_onDefault() throws Exception {

    TestApplication app = new TestApplication();
    String instancePath = InstanceHelpers.computeInstancePath(app.getMySqlVm());
    String t1 = this.mngr.createTarget("prop: ok\nid: t1\nhandler: h");
    String t2 = this.mngr.createTarget("prop: ok\nid: t2\nhandler: h");

    // Association is on the template and BY DEFAULT
    Assert.assertNull(this.mngr.findTargetId(app, instancePath));
    this.mngr.associateTargetWith(t1, app.getTemplate(), null);
    Assert.assertNull(this.mngr.findTargetId(app, instancePath));

    this.mngr.copyOriginalMapping(app);
    Assert.assertEquals(t1, this.mngr.findTargetId(app, instancePath));

    // We can override the association
    this.mngr.associateTargetWith(t2, app, instancePath);
    Assert.assertEquals(t2, this.mngr.findTargetId(app, instancePath));
  }
  @Test
  public void testCopyOriginalMapping_withComponents() throws Exception {

    TestApplication app = new TestApplication();
    String instancePath = InstanceHelpers.computeInstancePath(app.getMySqlVm());
    String t1 = this.mngr.createTarget("prop: ok\nid: t1\nhandler: h");
    String t2 = this.mngr.createTarget("prop: ok\nid: t2\nhandler: h");

    // Association is on the template and BY DEFAULT
    Assert.assertNull(this.mngr.findTargetId(app, instancePath));
    this.mngr.associateTargetWith(t1, app.getTemplate(), null);

    Assert.assertNull(this.mngr.findTargetId(app.getTemplate(), instancePath, true));
    Assert.assertEquals(t1, this.mngr.findTargetId(app.getTemplate(), instancePath, false));
    Assert.assertNull(this.mngr.findTargetId(app, instancePath, true));
    Assert.assertNull(this.mngr.findTargetId(app, instancePath, false));

    this.mngr.associateTargetWith(
        t2, app.getTemplate(), "@" + app.getMySqlVm().getComponent().getName());

    Assert.assertNull(this.mngr.findTargetId(app.getTemplate(), instancePath, true));
    Assert.assertEquals(t2, this.mngr.findTargetId(app.getTemplate(), instancePath, false));
    Assert.assertNull(this.mngr.findTargetId(app, instancePath, true));
    Assert.assertNull(this.mngr.findTargetId(app, instancePath, false));

    // Copy the mapping
    this.mngr.copyOriginalMapping(app);
    Assert.assertNull(this.mngr.findTargetId(app, instancePath, true));
    Assert.assertEquals(t2, this.mngr.findTargetId(app, instancePath, false));

    // Remove the component association
    this.mngr.dissociateTargetFrom(app, "@" + app.getMySqlVm().getComponent().getName());
    Assert.assertNull(this.mngr.findTargetId(app, instancePath, true));
    Assert.assertEquals(t1, this.mngr.findTargetId(app, instancePath, false));

    // We can override the association
    this.mngr.associateTargetWith(t2, app, instancePath);
    Assert.assertEquals(t2, this.mngr.findTargetId(app, instancePath, true));
    Assert.assertEquals(t2, this.mngr.findTargetId(app, instancePath, false));
  }
  @Test
  public void testApplicationWasDeleted() throws Exception {

    // Prepare the model
    TestApplication app1 = new TestApplication();
    app1.name("app1");
    TestApplication app2 = new TestApplication();
    app2.name("app2");

    String t1 =
        this.mngr.createTarget(
            "id: t1\nprop: ok\nname: target 1\ndescription: t1's target\nhandler: h");
    String t2 = this.mngr.createTarget("id: t2\nprop: ok\nhandler: docker");

    String path = InstanceHelpers.computeInstancePath(app1.getTomcatVm());

    // Create hints and associations
    this.mngr.associateTargetWith(t1, app1.getTemplate(), null);
    this.mngr.associateTargetWith(t1, app1, null);
    this.mngr.associateTargetWith(t2, app1, path);
    this.mngr.associateTargetWith(t2, app2, null);

    this.mngr.addHint(t1, app1);
    this.mngr.addHint(t2, app1);
    this.mngr.addHint(t2, app2);

    // Verify preconditions
    Assert.assertEquals(t1, this.mngr.findTargetId(app1, null));
    Assert.assertEquals(t2, this.mngr.findTargetId(app1, path));
    Assert.assertEquals(2, this.mngr.listPossibleTargets(app1).size());

    Assert.assertEquals(t2, this.mngr.findTargetId(app2, null));
    Assert.assertEquals(t2, this.mngr.findTargetId(app2, path));
    Assert.assertEquals(1, this.mngr.listPossibleTargets(app2).size());

    Assert.assertEquals(t1, this.mngr.findTargetId(app1.getTemplate(), path));
    Assert.assertEquals(0, this.mngr.listPossibleTargets(app1.getTemplate()).size());

    // Delete the application
    this.mngr.applicationWasDeleted(app1);

    // Verify post-conditions
    Assert.assertNull(this.mngr.findTargetId(app1, null));
    Assert.assertNull(this.mngr.findTargetId(app1, path));

    // t1 has not hint anymore, so it becomes global
    List<TargetWrapperDescriptor> hints = this.mngr.listPossibleTargets(app1);
    Assert.assertEquals(1, hints.size());
    Assert.assertEquals(t1, hints.get(0).getId());

    Assert.assertEquals(t2, this.mngr.findTargetId(app2, null));
    Assert.assertEquals(t2, this.mngr.findTargetId(app2, path));

    // t1 is global now
    Assert.assertEquals(2, this.mngr.listPossibleTargets(app2).size());

    // t1 is global now
    Assert.assertEquals(t1, this.mngr.findTargetId(app1.getTemplate(), path));
    Assert.assertEquals(1, this.mngr.listPossibleTargets(app1.getTemplate()).size());

    // Delete the template of app1
    this.mngr.applicationWasDeleted(app1.getTemplate());

    // Verify post-conditions
    Assert.assertNull(this.mngr.findTargetId(app1, null));
    Assert.assertNull(this.mngr.findTargetId(app1, path));
    Assert.assertEquals(1, this.mngr.listPossibleTargets(app1).size());

    Assert.assertEquals(t2, this.mngr.findTargetId(app2, null));
    Assert.assertEquals(t2, this.mngr.findTargetId(app2, path));
    Assert.assertEquals(2, this.mngr.listPossibleTargets(app2).size());

    Assert.assertNull(this.mngr.findTargetId(app1.getTemplate(), path));
    Assert.assertEquals(1, this.mngr.listPossibleTargets(app1.getTemplate()).size());

    // Delete app2
    this.mngr.applicationWasDeleted(app2);

    // Verify post-conditions
    // t2 does not have any hint anymore => it is global
    Assert.assertNull(this.mngr.findTargetId(app1, null));
    Assert.assertNull(this.mngr.findTargetId(app1, path));
    Assert.assertEquals(2, this.mngr.listPossibleTargets(app1).size());

    Assert.assertNull(this.mngr.findTargetId(app2, null));
    Assert.assertNull(this.mngr.findTargetId(app2, path));
    Assert.assertEquals(2, this.mngr.listPossibleTargets(app2).size());

    Assert.assertNull(this.mngr.findTargetId(app1.getTemplate(), path));
    Assert.assertEquals(2, this.mngr.listPossibleTargets(app1.getTemplate()).size());
  }