/**
   * Tests a somewhat contrived upgrade scenario with persistent classes A and B that can be
   * embedded in an entity without changing the entity class definition or version. For example, if
   * a field of type Animal has subclasses Cat and Dog, these subclasses will not be known to the
   * DPL until an instance of them is stored. When a new subclass is defined in the app, a metadata
   * upgrade will not occur until an instance is stored.
   *
   * <p>The contrived scenario is:
   *
   * <p>+ App initially contains persistent class A, but no instance of A is stored. Neither the
   * Master nor Replica DPL is aware of class A.
   *
   * <p>+ App is modified to contain new persistent class B.
   *
   * <p>+ Replica is upgraded, but does not enter Replica Upgrade Mode because class A and B are not
   * yet used or referenced.
   *
   * <p>+ Master writes record containing instance of A, but Replica does not read it. Replica
   * metadata is stale. It so happens that A is assigned format ID 200 by the Master.
   *
   * <p>+ Master is bounced and former Replica is elected Master.
   *
   * <p>+ New Master attempts to write record with instances of B, and updates its metadata, and
   * happens to assign B format ID 200. If the metadata previously written by the old Master is
   * overwritten, then metadata corruption will occur. Class A and B will have been assigned the
   * same format ID.
   *
   * <p>+ When any node reads record containing A, some sort of exception will probably occur as a
   * result of the incorrect format ID, or perhaps incorrect data will be returned.
   *
   * <p>This problem should be avoided because the new Master should detect that its metadata is
   * stale, and refresh it prior to writing the new metadata. It detects this, even though it is not
   * in Replica Upgrade Mode, by reading the metadata before updating it, and checking to see if it
   * has changed since it was last read. See PersistCatalog.writeDataCheckStale.
   *
   * <p>The scenario is contrived in the sense that it is very unlikely that an instance of A will
   * happen to be written by the Master for the very first time during the upgrade process. But it
   * does provide a test case for the detection of metadata changes in PersistCatalog.writeData.
   */
  @Test
  public void testRefreshBeforeWrite() throws Exception {

    doInitDuringOpen = false;
    open();

    masterApp.insertNullAnimal();
    replicaApp1.readNullAnimal();
    replicaApp2.readNullAnimal();

    /* Replicas upgraded to v1 but do not enter Replica Upgrade Mode. */
    bounceReplica1(1);
    bounceReplica2(1);
    assertFalse(replicaApp1.getStore().isReplicaUpgradeMode());
    assertFalse(replicaApp2.getStore().isReplicaUpgradeMode());

    masterApp.insertDogAnimal();
    bounceMaster(1);
    masterApp.insertCatAnimal();

    masterApp.readDogAnimal();
    masterApp.readCatAnimal();
    replicaApp1.readDogAnimal();
    replicaApp1.readCatAnimal();
    replicaApp2.readDogAnimal();
    replicaApp2.readCatAnimal();

    close();
  }