mirror of
https://github.com/google/nomulus.git
synced 2025-07-07 03:33:28 +02:00
Refactor SignedMarkRevocationListDao for easy primary database cutover (#943)
* Refactor SignedMarkRevocationListDao for easy primary database cutover * Fix javadoc comments * Use PrimaryDatabase enum * format fix * fix up tests * Fix punctuation * Remove unnecessary else ifs * Fix error messages * spell out class name
This commit is contained in:
parent
f86936788e
commit
bcc1924b24
6 changed files with 381 additions and 184 deletions
|
@ -16,21 +16,35 @@ package google.registry.model.smd;
|
|||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.model.EntityTestCase;
|
||||
import google.registry.model.common.DatabaseTransitionSchedule;
|
||||
import google.registry.model.common.DatabaseTransitionSchedule.PrimaryDatabase;
|
||||
import google.registry.model.common.DatabaseTransitionSchedule.PrimaryDatabaseTransition;
|
||||
import google.registry.model.common.DatabaseTransitionSchedule.TransitionId;
|
||||
import google.registry.model.common.TimedTransitionProperty;
|
||||
import google.registry.persistence.transaction.JpaTestRules;
|
||||
import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageExtension;
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.SystemPropertyExtension;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
@DualDatabaseTest
|
||||
public class SignedMarkRevocationListDaoTest {
|
||||
|
||||
private final FakeClock fakeClock = new FakeClock();
|
||||
public class SignedMarkRevocationListDaoTest extends EntityTestCase {
|
||||
|
||||
@RegisterExtension
|
||||
final JpaIntegrationWithCoverageExtension jpa =
|
||||
|
@ -40,50 +54,186 @@ public class SignedMarkRevocationListDaoTest {
|
|||
@Order(value = 1)
|
||||
final DatastoreEntityExtension datastoreEntityExtension = new DatastoreEntityExtension();
|
||||
|
||||
@Test
|
||||
void testSave_success() {
|
||||
@RegisterExtension
|
||||
@Order(value = Integer.MAX_VALUE)
|
||||
final SystemPropertyExtension systemPropertyExtension = new SystemPropertyExtension();
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
fakeClock.setTo(DateTime.parse("1984-12-21T00:00:00.000Z"));
|
||||
DatabaseTransitionSchedule schedule =
|
||||
DatabaseTransitionSchedule.create(
|
||||
TransitionId.SIGNED_MARK_REVOCATION_LIST,
|
||||
TimedTransitionProperty.fromValueMap(
|
||||
ImmutableSortedMap.of(
|
||||
START_OF_TIME,
|
||||
PrimaryDatabase.DATASTORE,
|
||||
fakeClock.nowUtc().plusDays(1),
|
||||
PrimaryDatabase.CLOUD_SQL),
|
||||
PrimaryDatabaseTransition.class));
|
||||
|
||||
tm().transactNew(() -> ofy().saveWithoutBackup().entity(schedule).now());
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testSave_datastorePrimary_success() {
|
||||
SignedMarkRevocationList list =
|
||||
SignedMarkRevocationList.create(
|
||||
fakeClock.nowUtc(), ImmutableMap.of("mark", fakeClock.nowUtc().minusHours(1)));
|
||||
SignedMarkRevocationListDao.trySave(list);
|
||||
SignedMarkRevocationList fromDb = SignedMarkRevocationListDao.getLatestRevision().get();
|
||||
SignedMarkRevocationListDao.save(list);
|
||||
SignedMarkRevocationList fromDb = SignedMarkRevocationListDao.load();
|
||||
assertAboutImmutableObjects().that(fromDb).isEqualExceptFields(list, "revisionId");
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testSave_cloudSqlPrimary_success() {
|
||||
fakeClock.advanceBy(Duration.standardDays(5));
|
||||
SignedMarkRevocationList list =
|
||||
SignedMarkRevocationList.create(
|
||||
fakeClock.nowUtc(), ImmutableMap.of("mark", fakeClock.nowUtc().minusHours(1)));
|
||||
SignedMarkRevocationListDao.save(list);
|
||||
SignedMarkRevocationList fromDb = SignedMarkRevocationListDao.load();
|
||||
assertAboutImmutableObjects().that(fromDb).isEqualExceptFields(list);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRetrieval_notPresent() {
|
||||
assertThat(SignedMarkRevocationListDao.getLatestRevision().isPresent()).isFalse();
|
||||
@TestOfyAndSql
|
||||
void testSaveAndLoad_datastorePrimary_emptyList() {
|
||||
SignedMarkRevocationList list =
|
||||
SignedMarkRevocationList.create(START_OF_TIME, ImmutableMap.of());
|
||||
SignedMarkRevocationListDao.save(list);
|
||||
SignedMarkRevocationList fromDb = SignedMarkRevocationListDao.load();
|
||||
assertAboutImmutableObjects().that(fromDb).isEqualExceptFields(list, "revisionId");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSaveAndRetrieval_emptyList() {
|
||||
@TestOfyAndSql
|
||||
void testSaveAndLoad_cloudSqlPrimary_emptyList() {
|
||||
fakeClock.advanceBy(Duration.standardDays(5));
|
||||
SignedMarkRevocationList list =
|
||||
SignedMarkRevocationList.create(fakeClock.nowUtc(), ImmutableMap.of());
|
||||
SignedMarkRevocationListDao.trySave(list);
|
||||
SignedMarkRevocationList fromDb = SignedMarkRevocationListDao.getLatestRevision().get();
|
||||
assertAboutImmutableObjects().that(fromDb).isEqualExceptFields(list);
|
||||
SignedMarkRevocationListDao.save(list);
|
||||
SignedMarkRevocationList fromDb = SignedMarkRevocationListDao.load();
|
||||
assertAboutImmutableObjects().that(fromDb).isEqualExceptFields(list, "revisionId");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSave_multipleVersions() {
|
||||
@TestOfyAndSql
|
||||
void testSave_datastorePrimary_multipleVersions() {
|
||||
SignedMarkRevocationList list =
|
||||
SignedMarkRevocationList.create(
|
||||
fakeClock.nowUtc(), ImmutableMap.of("mark", fakeClock.nowUtc().minusHours(1)));
|
||||
SignedMarkRevocationListDao.trySave(list);
|
||||
assertThat(
|
||||
SignedMarkRevocationListDao.getLatestRevision()
|
||||
.get()
|
||||
.isSmdRevoked("mark", fakeClock.nowUtc()))
|
||||
SignedMarkRevocationListDao.save(list);
|
||||
assertThat(SignedMarkRevocationListDao.load().isSmdRevoked("mark", fakeClock.nowUtc()))
|
||||
.isTrue();
|
||||
|
||||
// Now remove the revocation
|
||||
SignedMarkRevocationList secondList =
|
||||
SignedMarkRevocationList.create(fakeClock.nowUtc(), ImmutableMap.of());
|
||||
SignedMarkRevocationListDao.trySave(secondList);
|
||||
assertThat(
|
||||
SignedMarkRevocationListDao.getLatestRevision()
|
||||
.get()
|
||||
.isSmdRevoked("mark", fakeClock.nowUtc()))
|
||||
SignedMarkRevocationListDao.save(secondList);
|
||||
assertThat(SignedMarkRevocationListDao.load().isSmdRevoked("mark", fakeClock.nowUtc()))
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testSave_cloudSqlPrimary_multipleVersions() {
|
||||
fakeClock.advanceBy(Duration.standardDays(5));
|
||||
SignedMarkRevocationList list =
|
||||
SignedMarkRevocationList.create(
|
||||
fakeClock.nowUtc(), ImmutableMap.of("mark", fakeClock.nowUtc().minusHours(1)));
|
||||
SignedMarkRevocationListDao.save(list);
|
||||
assertThat(SignedMarkRevocationListDao.load().isSmdRevoked("mark", fakeClock.nowUtc()))
|
||||
.isTrue();
|
||||
|
||||
// Now remove the revocation
|
||||
SignedMarkRevocationList secondList =
|
||||
SignedMarkRevocationList.create(fakeClock.nowUtc(), ImmutableMap.of());
|
||||
SignedMarkRevocationListDao.save(secondList);
|
||||
assertThat(SignedMarkRevocationListDao.load().isSmdRevoked("mark", fakeClock.nowUtc()))
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testLoad_datastorePrimary_unequalLists() {
|
||||
SignedMarkRevocationList list =
|
||||
SignedMarkRevocationList.create(
|
||||
fakeClock.nowUtc(), ImmutableMap.of("mark", fakeClock.nowUtc().minusHours(1)));
|
||||
SignedMarkRevocationListDao.save(list);
|
||||
SignedMarkRevocationList list2 =
|
||||
SignedMarkRevocationList.create(
|
||||
fakeClock.nowUtc(), ImmutableMap.of("mark", fakeClock.nowUtc().minusHours(3)));
|
||||
jpaTm().transact(() -> jpaTm().put(list2));
|
||||
RuntimeException thrown =
|
||||
assertThrows(RuntimeException.class, SignedMarkRevocationListDao::load);
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.contains(
|
||||
"SMD mark has key 1984-12-20T23:00:00.000Z in DATASTORE and key"
|
||||
+ " 1984-12-20T21:00:00.000Z in secondary database.");
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testLoad_cloudSqlPrimary_unequalLists() {
|
||||
fakeClock.advanceBy(Duration.standardDays(5));
|
||||
SignedMarkRevocationList list =
|
||||
SignedMarkRevocationList.create(
|
||||
fakeClock.nowUtc(), ImmutableMap.of("mark", fakeClock.nowUtc().minusHours(1)));
|
||||
SignedMarkRevocationListDao.save(list);
|
||||
SignedMarkRevocationList list2 =
|
||||
SignedMarkRevocationList.create(
|
||||
fakeClock.nowUtc(), ImmutableMap.of("mark", fakeClock.nowUtc().minusHours(3)));
|
||||
jpaTm().transact(() -> jpaTm().put(list2));
|
||||
RuntimeException thrown =
|
||||
assertThrows(RuntimeException.class, SignedMarkRevocationListDao::load);
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.contains(
|
||||
"SMD mark has key 1984-12-25T21:00:00.000Z in CLOUD_SQL and key"
|
||||
+ " 1984-12-25T23:00:00.000Z in secondary database.");
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testLoad_cloudSqlPrimary_unequalLists_succeedsInProduction() {
|
||||
RegistryEnvironment.PRODUCTION.setup(systemPropertyExtension);
|
||||
fakeClock.advanceBy(Duration.standardDays(5));
|
||||
SignedMarkRevocationList list =
|
||||
SignedMarkRevocationList.create(
|
||||
fakeClock.nowUtc(), ImmutableMap.of("mark", fakeClock.nowUtc().minusHours(1)));
|
||||
SignedMarkRevocationListDao.save(list);
|
||||
SignedMarkRevocationList list2 =
|
||||
SignedMarkRevocationList.create(
|
||||
fakeClock.nowUtc(), ImmutableMap.of("mark", fakeClock.nowUtc().minusHours(3)));
|
||||
jpaTm().transact(() -> jpaTm().put(list2));
|
||||
SignedMarkRevocationList fromDb = SignedMarkRevocationListDao.load();
|
||||
assertAboutImmutableObjects().that(fromDb).isEqualExceptFields(list2, "revisionId");
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testLoad_datastorePrimary_noListInCloudSql() {
|
||||
SignedMarkRevocationList list =
|
||||
SignedMarkRevocationList.create(
|
||||
fakeClock.nowUtc(), ImmutableMap.of("mark", fakeClock.nowUtc().minusHours(1)));
|
||||
SignedMarkRevocationListDao.save(list);
|
||||
jpaTm().transact(() -> jpaTm().delete(list));
|
||||
RuntimeException thrown =
|
||||
assertThrows(RuntimeException.class, SignedMarkRevocationListDao::load);
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.contains(
|
||||
"SignedMarkRevocationList in Cloud SQL is empty while it is not empty in the"
|
||||
+ " primary database.");
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testLoad_cloudSqlPrimary_noListInDatastore() {
|
||||
fakeClock.advanceBy(Duration.standardDays(5));
|
||||
SignedMarkRevocationList list =
|
||||
SignedMarkRevocationList.create(
|
||||
fakeClock.nowUtc(), ImmutableMap.of("mark", fakeClock.nowUtc().minusHours(1)));
|
||||
jpaTm().transact(() -> jpaTm().put(list));
|
||||
RuntimeException thrown =
|
||||
assertThrows(RuntimeException.class, SignedMarkRevocationListDao::load);
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.contains(
|
||||
"SignedMarkRevocationList in Datastore is empty while it is not empty in the"
|
||||
+ " primary database.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,18 +139,6 @@ public class SignedMarkRevocationListTest {
|
|||
.isEqualTo(DateTime.parse("2000-01-01T00:00:00Z"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_getCreationTime_missingInCloudSQL() {
|
||||
clock.setTo(DateTime.parse("2000-01-01T00:00:00Z"));
|
||||
createSaveGetHelper(1);
|
||||
jpaTm().transact(() -> jpaTm().delete(SignedMarkRevocationListDao.getLatestRevision().get()));
|
||||
RuntimeException thrown =
|
||||
assertThrows(RuntimeException.class, () -> SignedMarkRevocationList.get());
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Signed mark revocation list in Cloud SQL is empty.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_getCreationTime_unequalListsInDatabases() {
|
||||
clock.setTo(DateTime.parse("2000-01-01T00:00:00Z"));
|
||||
|
@ -159,11 +147,15 @@ public class SignedMarkRevocationListTest {
|
|||
for (int i = 0; i < 3; i++) {
|
||||
revokes.put(Integer.toString(i), clock.nowUtc());
|
||||
}
|
||||
SignedMarkRevocationListDao.trySave(
|
||||
SignedMarkRevocationList.create(clock.nowUtc(), revokes.build()));
|
||||
jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.getEntityManager()
|
||||
.persist(SignedMarkRevocationList.create(clock.nowUtc(), revokes.build())));
|
||||
RuntimeException thrown =
|
||||
assertThrows(RuntimeException.class, () -> SignedMarkRevocationList.get());
|
||||
assertThat(thrown).hasMessageThat().contains("Unequal SM revocation lists detected:");
|
||||
assertThat(thrown).hasMessageThat().contains("Unequal SignedMarkRevocationList detected:");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue