@Test
  public void testEntityManagementLifecycleAndVisibilityDuringRebind() throws Exception {
    MyLatchingEntityImpl.latching = false;
    MyLatchingEntity origE =
        origApp.createAndManageChild(EntitySpec.create(MyLatchingEntity.class));
    MyLatchingEntityImpl.reset(); // after origE has been managed
    MyLatchingEntityImpl.latching = true;

    // Serialize and rebind, but don't yet manage the app
    RebindTestUtils.waitForPersisted(origApp);
    RebindTestUtils.checkCurrentMementoSerializable(origApp);
    newManagementContext =
        RebindTestUtils.newPersistingManagementContextUnstarted(mementoDir, classLoader);
    Thread thread =
        new Thread() {
          public void run() {
            try {
              newManagementContext.getRebindManager().rebind(classLoader);
            } catch (Exception e) {
              throw Throwables.propagate(e);
            }
          }
        };
    try {
      thread.start();

      assertTrue(Durations.await(MyLatchingEntityImpl.reconstructStartedLatch, TIMEOUT_MS));
      assertNull(newManagementContext.getEntityManager().getEntity(origApp.getId()));
      assertNull(newManagementContext.getEntityManager().getEntity(origE.getId()));
      assertTrue(MyLatchingEntityImpl.managingStartedLatch.getCount() > 0);

      MyLatchingEntityImpl.reconstructContinuesLatch.countDown();
      assertTrue(Durations.await(MyLatchingEntityImpl.managingStartedLatch, TIMEOUT_MS));
      assertNotNull(newManagementContext.getEntityManager().getEntity(origApp.getId()));
      assertNull(newManagementContext.getEntityManager().getEntity(origE.getId()));
      assertTrue(MyLatchingEntityImpl.managedStartedLatch.getCount() > 0);

      MyLatchingEntityImpl.managingContinuesLatch.countDown();
      assertTrue(Durations.await(MyLatchingEntityImpl.managedStartedLatch, TIMEOUT_MS));
      assertNotNull(newManagementContext.getEntityManager().getEntity(origApp.getId()));
      assertNotNull(newManagementContext.getEntityManager().getEntity(origE.getId()));
      MyLatchingEntityImpl.managedContinuesLatch.countDown();

      Durations.join(thread, TIMEOUT_MS);
      assertFalse(thread.isAlive());

    } finally {
      thread.interrupt();
      MyLatchingEntityImpl.reset();
    }
  }
  @Test(groups = "Integration") // takes more than 4 seconds, due to assertContinually calls
  public void testSubscriptionAndPublishingOnlyActiveWhenEntityIsManaged() throws Exception {
    MyLatchingEntityImpl.latching = false;
    origApp.createAndManageChild(
        EntitySpec.create(MyLatchingEntity.class)
            .configure("subscribe", TestApplication.MY_ATTRIBUTE)
            .configure("publish", "myvaltopublish"));
    MyLatchingEntityImpl.reset(); // after origE has been managed
    MyLatchingEntityImpl.latching = true;

    // Serialize and rebind, but don't yet manage the app
    RebindTestUtils.waitForPersisted(origApp);
    RebindTestUtils.checkCurrentMementoSerializable(origApp);
    newManagementContext = new LocalManagementContext();
    Thread thread =
        new Thread() {
          public void run() {
            try {
              RebindTestUtils.rebind(newManagementContext, mementoDir, getClass().getClassLoader());
            } catch (Exception e) {
              throw Throwables.propagate(e);
            }
          }
        };
    try {
      thread.start();
      final List<Object> events = new CopyOnWriteArrayList<Object>();

      newManagementContext
          .getSubscriptionManager()
          .subscribe(
              null,
              MyLatchingEntityImpl.MY_SENSOR,
              new SensorEventListener<Object>() {
                @Override
                public void onEvent(SensorEvent<Object> event) {
                  events.add(event.getValue());
                }
              });

      // In entity's reconstruct, publishes events are queued, and subscriptions don't yet take
      // effect
      assertTrue(Durations.await(MyLatchingEntityImpl.reconstructStartedLatch, TIMEOUT_MS));
      newManagementContext
          .getSubscriptionManager()
          .publish(
              new BasicSensorEvent<String>(TestApplication.MY_ATTRIBUTE, null, "myvaltooearly"));

      Asserts.continually(
          Suppliers.ofInstance(MyLatchingEntityImpl.events),
          Predicates.equalTo(Collections.emptyList()));
      Asserts.continually(
          Suppliers.ofInstance(events), Predicates.equalTo(Collections.emptyList()));

      // When the entity is notified of "managing", then subscriptions take effect (but missed
      // events not delivered);
      // published events remain queued
      MyLatchingEntityImpl.reconstructContinuesLatch.countDown();
      assertTrue(MyLatchingEntityImpl.managingStartedLatch.getCount() > 0);

      Asserts.continually(
          Suppliers.ofInstance(events), Predicates.equalTo(Collections.emptyList()));
      Asserts.continually(
          Suppliers.ofInstance(MyLatchingEntityImpl.events),
          Predicates.equalTo(Collections.emptyList()));

      newManagementContext
          .getSubscriptionManager()
          .publish(
              new BasicSensorEvent<String>(TestApplication.MY_ATTRIBUTE, null, "myvaltoreceive"));
      Asserts.eventually(
          Suppliers.ofInstance(MyLatchingEntityImpl.events),
          Predicates.<List<Object>>equalTo(ImmutableList.of((Object) "myvaltoreceive")));

      // When the entity is notified of "managed", its events are only then delivered
      MyLatchingEntityImpl.managingContinuesLatch.countDown();
      assertTrue(Durations.await(MyLatchingEntityImpl.managedStartedLatch, TIMEOUT_MS));

      Asserts.eventually(
          Suppliers.ofInstance(MyLatchingEntityImpl.events),
          Predicates.<List<Object>>equalTo(ImmutableList.of((Object) "myvaltoreceive")));

      MyLatchingEntityImpl.managedContinuesLatch.countDown();

      Durations.join(thread, TIMEOUT_MS);
      assertFalse(thread.isAlive());

    } finally {
      thread.interrupt();
      MyLatchingEntityImpl.reset();
    }
  }