mirror of
https://github.com/google/nomulus.git
synced 2025-07-07 03:33:28 +02:00
Refactor PremiumList storage and retrieval for dual-database setup (#950)
* Refactor PremiumList storage and retrieval for dual-database setup Previously, the storage and retrieval code was scattered across various places haphazardly and there was no good way to set up dual database access. This reorganizes the code so that retrieval is simpler and it allows for dual-write and dual-read. This includes the following changes: - Move all static / object retrieval code out of PremiumList -- the class should solely consist of its data and methods on its data and it shouldn't have to worry about complicated caching or retrieval - Split all PremiumList retrieval methods into PremiumListDatastoreDao and PremiumListSqlDao that handle retrieval of the premium list entry objects from the corresponding databases (since the way the actual data itself is stored is not the same between the two - Create a dual-DAO for PremiumList retrieval that branches between SQL/Datastore depending on which is appropriate -- it will read from and write to both but only log errors for the secondary DB - Cache the mapping from name to premium list in the dual-DAO. This is a common code path regardless of database so we can cache it at a high level - Cache the ways to go from premium list -> premium entries in the Datastore and SQL DAOs. These caches are specific to the corresponding DB and should thus be stored in the corresponding DAO. - Moves the database-choosing code from the actions to the lower-level dual-DAO. This is because we will often wish to access this premium list data in flows and all accesses should use the proper DB-selecting code
This commit is contained in:
parent
ffe3124ee1
commit
a07fbb27c5
37 changed files with 1270 additions and 1046 deletions
|
@ -53,6 +53,7 @@ import google.registry.model.ofy.CommitLogBucket;
|
|||
import google.registry.model.ofy.CommitLogManifest;
|
||||
import google.registry.model.ofy.CommitLogMutation;
|
||||
import google.registry.model.registrar.RegistrarContact;
|
||||
import google.registry.model.registry.label.PremiumList;
|
||||
import google.registry.model.registry.label.ReservedList;
|
||||
import google.registry.model.server.Lock;
|
||||
import google.registry.model.tmch.ClaimsListShard;
|
||||
|
@ -93,13 +94,14 @@ public class ReplayCommitLogsToSqlActionTest {
|
|||
.withClock(fakeClock)
|
||||
.withOfyTestEntities(TestObject.class)
|
||||
.withJpaUnitTestEntities(
|
||||
RegistrarContact.class,
|
||||
TestObject.class,
|
||||
SqlReplayCheckpoint.class,
|
||||
ContactResource.class,
|
||||
DelegationSignerData.class,
|
||||
DomainBase.class,
|
||||
GracePeriod.class,
|
||||
DelegationSignerData.class)
|
||||
PremiumList.class,
|
||||
RegistrarContact.class,
|
||||
SqlReplayCheckpoint.class,
|
||||
TestObject.class)
|
||||
.build();
|
||||
|
||||
/** Local GCS service. */
|
||||
|
|
|
@ -34,6 +34,9 @@ import google.registry.model.domain.DomainBase;
|
|||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.transaction.JpaTestRules;
|
||||
import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationTestExtension;
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.tools.LevelDbLogReader;
|
||||
|
@ -48,6 +51,7 @@ import org.apache.beam.sdk.values.KV;
|
|||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
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;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
@ -58,6 +62,15 @@ public class BackupTestStoreTest {
|
|||
|
||||
@TempDir File tempDir;
|
||||
|
||||
@RegisterExtension
|
||||
final transient JpaIntegrationTestExtension jpaIntegrationTestExtension =
|
||||
new JpaTestRules.Builder().buildIntegrationTestRule();
|
||||
|
||||
@RegisterExtension
|
||||
@Order(value = 1)
|
||||
final transient DatastoreEntityExtension datastoreEntityExtension =
|
||||
new DatastoreEntityExtension();
|
||||
|
||||
@RegisterExtension InjectExtension injectRule = new InjectExtension();
|
||||
|
||||
private FakeClock fakeClock;
|
||||
|
|
|
@ -26,6 +26,9 @@ import google.registry.model.contact.ContactResource;
|
|||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.persistence.transaction.JpaTestRules;
|
||||
import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationTestExtension;
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import java.io.File;
|
||||
|
@ -44,6 +47,7 @@ import org.apache.beam.sdk.values.PCollection;
|
|||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
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;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
@ -52,6 +56,7 @@ import org.junit.jupiter.api.io.TempDir;
|
|||
class CommitLogTransformsTest implements Serializable {
|
||||
|
||||
private static final DateTime START_TIME = DateTime.parse("2000-01-01T00:00:00.0Z");
|
||||
private final FakeClock fakeClock = new FakeClock(START_TIME);
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@TempDir
|
||||
|
@ -59,11 +64,19 @@ class CommitLogTransformsTest implements Serializable {
|
|||
|
||||
@RegisterExtension final transient InjectExtension injectRule = new InjectExtension();
|
||||
|
||||
@RegisterExtension
|
||||
final transient JpaIntegrationTestExtension jpaIntegrationTestExtension =
|
||||
new JpaTestRules.Builder().withClock(fakeClock).buildIntegrationTestRule();
|
||||
|
||||
@RegisterExtension
|
||||
@Order(value = 1)
|
||||
final transient DatastoreEntityExtension datastoreEntityExtension =
|
||||
new DatastoreEntityExtension();
|
||||
|
||||
@RegisterExtension
|
||||
final transient TestPipelineExtension testPipeline =
|
||||
TestPipelineExtension.create().enableAbandonedNodeEnforcement(true);
|
||||
|
||||
private FakeClock fakeClock;
|
||||
private transient BackupTestStore store;
|
||||
private File commitLogsDir;
|
||||
private File firstCommitLogFile;
|
||||
|
@ -75,7 +88,6 @@ class CommitLogTransformsTest implements Serializable {
|
|||
|
||||
@BeforeEach
|
||||
void beforeEach() throws Exception {
|
||||
fakeClock = new FakeClock(START_TIME);
|
||||
store = new BackupTestStore(fakeClock);
|
||||
injectRule.setStaticField(Ofy.class, "clock", fakeClock);
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ public class DomainBaseUtilTest {
|
|||
|
||||
@RegisterExtension
|
||||
AppEngineExtension appEngineRule =
|
||||
AppEngineExtension.builder().withDatastore().withClock(fakeClock).build();
|
||||
AppEngineExtension.builder().withDatastoreAndCloudSql().withClock(fakeClock).build();
|
||||
|
||||
@RegisterExtension InjectExtension injectRule = new InjectExtension();
|
||||
|
||||
|
|
|
@ -27,6 +27,9 @@ import google.registry.model.contact.ContactResource;
|
|||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.persistence.transaction.JpaTestRules;
|
||||
import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationTestExtension;
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import java.io.File;
|
||||
|
@ -44,6 +47,7 @@ import org.apache.beam.sdk.values.PCollection;
|
|||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
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;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
@ -53,7 +57,7 @@ import org.junit.jupiter.api.io.TempDir;
|
|||
*
|
||||
* <p>This class implements {@link Serializable} so that test {@link DoFn} classes may be inlined.
|
||||
*/
|
||||
class ExportloadingTransformsTest implements Serializable {
|
||||
class ExportLoadingTransformsTest implements Serializable {
|
||||
|
||||
private static final DateTime START_TIME = DateTime.parse("2000-01-01T00:00:00.0Z");
|
||||
|
||||
|
@ -68,6 +72,15 @@ class ExportloadingTransformsTest implements Serializable {
|
|||
|
||||
@RegisterExtension final transient InjectExtension injectRule = new InjectExtension();
|
||||
|
||||
@RegisterExtension
|
||||
final transient JpaIntegrationTestExtension jpaIntegrationTestExtension =
|
||||
new JpaTestRules.Builder().buildIntegrationTestRule();
|
||||
|
||||
@RegisterExtension
|
||||
@Order(value = 1)
|
||||
final transient DatastoreEntityExtension datastoreEntityExtension =
|
||||
new DatastoreEntityExtension();
|
||||
|
||||
@RegisterExtension
|
||||
final transient TestPipelineExtension testPipeline =
|
||||
TestPipelineExtension.create().enableAbandonedNodeEnforcement(true);
|
|
@ -29,6 +29,9 @@ import google.registry.model.domain.DomainBase;
|
|||
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.persistence.transaction.JpaTestRules;
|
||||
import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationTestExtension;
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import java.io.File;
|
||||
|
@ -38,6 +41,7 @@ import org.apache.beam.sdk.values.KV;
|
|||
import org.apache.beam.sdk.values.PCollectionTuple;
|
||||
import org.joda.time.DateTime;
|
||||
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;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
@ -84,6 +88,15 @@ class LoadDatastoreSnapshotTest {
|
|||
|
||||
@RegisterExtension final transient InjectExtension injectRule = new InjectExtension();
|
||||
|
||||
@RegisterExtension
|
||||
final transient JpaIntegrationTestExtension jpaIntegrationTestExtension =
|
||||
new JpaTestRules.Builder().buildIntegrationTestRule();
|
||||
|
||||
@RegisterExtension
|
||||
@Order(value = 1)
|
||||
final transient DatastoreEntityExtension datastoreEntityExtension =
|
||||
new DatastoreEntityExtension();
|
||||
|
||||
@RegisterExtension
|
||||
final transient TestPipelineExtension testPipeline =
|
||||
TestPipelineExtension.create().enableAbandonedNodeEnforcement(true);
|
||||
|
|
|
@ -17,8 +17,6 @@ package google.registry.export;
|
|||
import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8;
|
||||
import static google.registry.export.ExportPremiumTermsAction.EXPORT_MIME_TYPE;
|
||||
import static google.registry.export.ExportPremiumTermsAction.PREMIUM_TERMS_FILENAME;
|
||||
import static google.registry.model.registry.label.PremiumListUtils.deletePremiumList;
|
||||
import static google.registry.model.registry.label.PremiumListUtils.savePremiumListAndEntries;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.deleteTld;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
|
@ -39,6 +37,7 @@ import com.google.common.collect.ImmutableList;
|
|||
import com.google.common.net.MediaType;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.model.registry.label.PremiumList;
|
||||
import google.registry.model.registry.label.PremiumListDualDao;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.storage.drive.DriveConnection;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
|
@ -76,8 +75,7 @@ public class ExportPremiumTermsActionTest {
|
|||
@BeforeEach
|
||||
void beforeEach() throws Exception {
|
||||
createTld("tld");
|
||||
PremiumList pl = new PremiumList.Builder().setName("pl-name").build();
|
||||
savePremiumListAndEntries(pl, PREMIUM_NAMES);
|
||||
PremiumList pl = PremiumListDualDao.save("pl-name", PREMIUM_NAMES);
|
||||
persistResource(
|
||||
Registry.get("tld").asBuilder().setPremiumList(pl).setDriveFolderId("folder_id").build());
|
||||
when(driveConnection.createOrUpdateFile(
|
||||
|
@ -106,26 +104,6 @@ public class ExportPremiumTermsActionTest {
|
|||
verifyNoMoreInteractions(response);
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_exportPremiumTerms_success_emptyPremiumList() throws IOException {
|
||||
PremiumList pl = new PremiumList.Builder().setName("pl-name").build();
|
||||
savePremiumListAndEntries(pl, ImmutableList.of());
|
||||
runAction("tld");
|
||||
|
||||
verify(driveConnection)
|
||||
.createOrUpdateFile(
|
||||
PREMIUM_TERMS_FILENAME,
|
||||
EXPORT_MIME_TYPE,
|
||||
"folder_id",
|
||||
DISCLAIMER_WITH_NEWLINE.getBytes(UTF_8));
|
||||
verifyNoMoreInteractions(driveConnection);
|
||||
|
||||
verify(response).setStatus(SC_OK);
|
||||
verify(response).setPayload("file_id");
|
||||
verify(response).setContentType(PLAIN_TEXT_UTF_8);
|
||||
verifyNoMoreInteractions(response);
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_exportPremiumTerms_doNothing_listNotConfigured() {
|
||||
persistResource(Registry.get("tld").asBuilder().setPremiumList(null).build());
|
||||
|
@ -165,7 +143,7 @@ public class ExportPremiumTermsActionTest {
|
|||
|
||||
@Test
|
||||
void test_exportPremiumTerms_failure_noPremiumList() {
|
||||
deletePremiumList(new PremiumList.Builder().setName("pl-name").build());
|
||||
PremiumListDualDao.delete(new PremiumList.Builder().setName("pl-name").build());
|
||||
assertThrows(RuntimeException.class, () -> runAction("tld"));
|
||||
|
||||
verifyNoInteractions(driveConnection);
|
||||
|
|
|
@ -41,6 +41,7 @@ import google.registry.model.EntityTestCase;
|
|||
import google.registry.model.registry.Registry.RegistryNotFoundException;
|
||||
import google.registry.model.registry.Registry.TldState;
|
||||
import google.registry.model.registry.label.PremiumList;
|
||||
import google.registry.model.registry.label.PremiumListDualDao;
|
||||
import google.registry.model.registry.label.ReservedList;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
|
@ -204,7 +205,7 @@ public class RegistryTest extends EntityTestCase {
|
|||
Registry registry = Registry.get("tld").asBuilder().setPremiumList(pl2).build();
|
||||
Key<PremiumList> plKey = registry.getPremiumList();
|
||||
assertThat(plKey).isNotNull();
|
||||
PremiumList stored = PremiumList.getUncached(plKey.getName()).get();
|
||||
PremiumList stored = PremiumListDualDao.getLatestRevision(plKey.getName()).get();
|
||||
assertThat(stored.getName()).isEqualTo("tld2");
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
package google.registry.model.registry.label;
|
||||
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth8.assertThat;
|
||||
import static com.google.monitoring.metrics.contrib.DistributionMetricSubject.assertThat;
|
||||
|
@ -26,37 +27,33 @@ import static google.registry.model.registry.label.DomainLabelMetrics.PremiumLis
|
|||
import static google.registry.model.registry.label.DomainLabelMetrics.PremiumListCheckOutcome.UNCACHED_POSITIVE;
|
||||
import static google.registry.model.registry.label.DomainLabelMetrics.premiumListChecks;
|
||||
import static google.registry.model.registry.label.DomainLabelMetrics.premiumListProcessingTime;
|
||||
import static google.registry.model.registry.label.PremiumListUtils.deletePremiumList;
|
||||
import static google.registry.model.registry.label.PremiumListUtils.doesPremiumListExist;
|
||||
import static google.registry.model.registry.label.PremiumListUtils.getPremiumPrice;
|
||||
import static google.registry.model.registry.label.PremiumListUtils.savePremiumListAndEntries;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerUtil.transactIfJpaTm;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.loadPremiumListEntries;
|
||||
import static google.registry.testing.DatabaseHelper.persistPremiumList;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static org.joda.time.Duration.standardDays;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.dns.writer.VoidDnsWriter;
|
||||
import google.registry.model.pricing.StaticPremiumListPricingEngine;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.model.registry.label.PremiumList.PremiumListEntry;
|
||||
import google.registry.model.registry.label.PremiumList.PremiumListRevision;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.TestCacheExtension;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import org.joda.money.Money;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link PremiumListUtils}. */
|
||||
public class PremiumListUtilsTest {
|
||||
/** Unit tests for {@link PremiumListDatastoreDao}. */
|
||||
public class PremiumListDatastoreDaoTest {
|
||||
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine =
|
||||
|
@ -70,11 +67,13 @@ public class PremiumListUtilsTest {
|
|||
.withPremiumListEntriesCache(standardDays(1))
|
||||
.build();
|
||||
|
||||
private PremiumList pl;
|
||||
|
||||
@BeforeEach
|
||||
void before() {
|
||||
// createTld() overwrites the premium list, so call it before persisting pl.
|
||||
createTld("tld");
|
||||
PremiumList pl =
|
||||
pl =
|
||||
persistPremiumList(
|
||||
"tld",
|
||||
"lol,USD 999 # yup",
|
||||
|
@ -98,66 +97,39 @@ public class PremiumListUtilsTest {
|
|||
.hasNoOtherValues();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetPremiumPrice_returnsNoPriceWhenNoPremiumListConfigured() {
|
||||
createTld("ghost");
|
||||
persistResource(
|
||||
new Registry.Builder()
|
||||
.setTldStr("ghost")
|
||||
.setPremiumPricingEngine(StaticPremiumListPricingEngine.NAME)
|
||||
.setDnsWriters(ImmutableSet.of(VoidDnsWriter.NAME))
|
||||
.build());
|
||||
assertThat(Registry.get("ghost").getPremiumList()).isNull();
|
||||
assertThat(getPremiumPrice("blah", Registry.get("ghost"))).isEmpty();
|
||||
assertThat(premiumListChecks).hasNoOtherValues();
|
||||
assertThat(premiumListProcessingTime).hasNoOtherValues();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetPremiumPrice_throwsExceptionWhenNonExistentPremiumListConfigured() {
|
||||
deletePremiumList(PremiumList.getUncached("tld").get());
|
||||
IllegalStateException thrown =
|
||||
assertThrows(
|
||||
IllegalStateException.class, () -> getPremiumPrice("blah", Registry.get("tld")));
|
||||
assertThat(thrown).hasMessageThat().contains("Could not load premium list 'tld'");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSave_largeNumberOfEntries_succeeds() {
|
||||
PremiumList premiumList = persistHumongousPremiumList("tld", 2500);
|
||||
assertThat(loadPremiumListEntries(premiumList)).hasSize(2500);
|
||||
assertThat(getPremiumPrice("7", Registry.get("tld"))).hasValue(Money.parse("USD 100"));
|
||||
assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "7", "tld"))
|
||||
.hasValue(Money.parse("USD 100"));
|
||||
assertMetricOutcomeCount(1, UNCACHED_POSITIVE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSave_updateTime_isUpdatedOnEverySave() {
|
||||
PremiumList pl =
|
||||
savePremiumListAndEntries(
|
||||
new PremiumList.Builder().setName("tld3").build(), ImmutableList.of("slime,USD 10"));
|
||||
PremiumList newPl =
|
||||
savePremiumListAndEntries(
|
||||
new PremiumList.Builder().setName(pl.getName()).build(),
|
||||
ImmutableList.of("mutants,USD 20"));
|
||||
PremiumList pl = PremiumListDatastoreDao.save("tld3", ImmutableList.of("slime,USD 10"));
|
||||
PremiumList newPl = PremiumListDatastoreDao.save("tld3", ImmutableList.of("mutants,USD 20"));
|
||||
assertThat(newPl.getLastUpdateTime()).isGreaterThan(pl.getLastUpdateTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSave_creationTime_onlyUpdatedOnFirstCreation() {
|
||||
PremiumList pl = persistPremiumList("tld3", "sludge,JPY 1000");
|
||||
PremiumList newPl = savePremiumListAndEntries(pl, ImmutableList.of("sleighbells,CHF 2000"));
|
||||
PremiumList newPl =
|
||||
PremiumListDatastoreDao.save("tld3", ImmutableList.of("sleighbells,CHF 2000"));
|
||||
assertThat(newPl.creationTime).isEqualTo(pl.creationTime);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExists() {
|
||||
assertThat(doesPremiumListExist("tld")).isTrue();
|
||||
assertThat(doesPremiumListExist("nonExistentPremiumList")).isFalse();
|
||||
assertThat(PremiumListDatastoreDao.getLatestRevision("tld")).isPresent();
|
||||
assertThat(PremiumListDatastoreDao.getLatestRevision("nonExistentPremiumList")).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetPremiumPrice_comesFromBloomFilter() throws Exception {
|
||||
PremiumList pl = PremiumList.getCached("tld").get();
|
||||
PremiumList pl = PremiumListDatastoreDao.getLatestRevision("tld").get();
|
||||
PremiumListEntry entry =
|
||||
persistResource(
|
||||
new PremiumListEntry.Builder()
|
||||
|
@ -167,10 +139,10 @@ public class PremiumListUtilsTest {
|
|||
.build());
|
||||
// "missingno" shouldn't be in the Bloom filter, thus it should return not premium without
|
||||
// attempting to load the entity that is actually present.
|
||||
assertThat(getPremiumPrice("missingno", Registry.get("tld"))).isEmpty();
|
||||
assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "missingno", "tld")).isEmpty();
|
||||
// However, if we manually query the cache to force an entity load, it should be found.
|
||||
assertThat(
|
||||
PremiumList.cachePremiumListEntries.get(
|
||||
PremiumListDatastoreDao.premiumListEntriesCache.get(
|
||||
Key.create(pl.getRevisionKey(), PremiumListEntry.class, "missingno")))
|
||||
.hasValue(entry);
|
||||
assertMetricOutcomeCount(1, BLOOM_FILTER_NEGATIVE);
|
||||
|
@ -178,8 +150,10 @@ public class PremiumListUtilsTest {
|
|||
|
||||
@Test
|
||||
void testGetPremiumPrice_cachedSecondTime() {
|
||||
assertThat(getPremiumPrice("rich", Registry.get("tld"))).hasValue(Money.parse("USD 1999"));
|
||||
assertThat(getPremiumPrice("rich", Registry.get("tld"))).hasValue(Money.parse("USD 1999"));
|
||||
assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "rich", "tld"))
|
||||
.hasValue(Money.parse("USD 1999"));
|
||||
assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "rich", "tld"))
|
||||
.hasValue(Money.parse("USD 1999"));
|
||||
assertThat(premiumListChecks)
|
||||
.hasValueForLabels(1, "tld", "tld", UNCACHED_POSITIVE.toString())
|
||||
.and()
|
||||
|
@ -197,20 +171,15 @@ public class PremiumListUtilsTest {
|
|||
@Test
|
||||
void testGetPremiumPrice_bloomFilterFalsePositive() {
|
||||
// Remove one of the premium list entries from behind the Bloom filter's back.
|
||||
tm()
|
||||
.transactNew(
|
||||
tm().transactNew(
|
||||
() ->
|
||||
ofy()
|
||||
.delete()
|
||||
.keys(
|
||||
Key.create(
|
||||
PremiumList.getCached("tld").get().getRevisionKey(),
|
||||
PremiumListEntry.class,
|
||||
"rich")));
|
||||
.keys(Key.create(pl.getRevisionKey(), PremiumListEntry.class, "rich")));
|
||||
ofy().clearSessionCache();
|
||||
|
||||
assertThat(getPremiumPrice("rich", Registry.get("tld"))).isEmpty();
|
||||
assertThat(getPremiumPrice("rich", Registry.get("tld"))).isEmpty();
|
||||
assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "rich", "tld")).isEmpty();
|
||||
assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "rich", "tld")).isEmpty();
|
||||
|
||||
assertThat(premiumListChecks)
|
||||
.hasValueForLabels(1, "tld", "tld", UNCACHED_NEGATIVE.toString())
|
||||
|
@ -228,22 +197,26 @@ public class PremiumListUtilsTest {
|
|||
|
||||
@Test
|
||||
void testSave_removedPremiumListEntries_areNoLongerInDatastore() {
|
||||
Registry registry = Registry.get("tld");
|
||||
PremiumList pl = persistPremiumList("tld", "genius,USD 10", "dolt,JPY 1000");
|
||||
assertThat(getPremiumPrice("genius", registry)).hasValue(Money.parse("USD 10"));
|
||||
assertThat(getPremiumPrice("dolt", registry)).hasValue(Money.parse("JPY 1000"));
|
||||
assertThat(ofy()
|
||||
.load()
|
||||
.type(PremiumListEntry.class)
|
||||
.parent(pl.getRevisionKey())
|
||||
.id("dolt")
|
||||
.now()
|
||||
.price)
|
||||
assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "genius", "tld"))
|
||||
.hasValue(Money.parse("USD 10"));
|
||||
assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "dolt", "tld"))
|
||||
.hasValue(Money.parse("JPY 1000"));
|
||||
assertThat(
|
||||
ofy()
|
||||
.load()
|
||||
.type(PremiumListEntry.class)
|
||||
.parent(pl.getRevisionKey())
|
||||
.id("dolt")
|
||||
.now()
|
||||
.price)
|
||||
.isEqualTo(Money.parse("JPY 1000"));
|
||||
savePremiumListAndEntries(pl, ImmutableList.of("genius,USD 10", "savant,USD 90"));
|
||||
assertThat(getPremiumPrice("genius", registry)).hasValue(Money.parse("USD 10"));
|
||||
assertThat(getPremiumPrice("savant", registry)).hasValue(Money.parse("USD 90"));
|
||||
assertThat(getPremiumPrice("dolt", registry)).isEmpty();
|
||||
PremiumListDatastoreDao.save("tld", ImmutableList.of("genius,USD 10", "savant,USD 90"));
|
||||
assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "genius", "tld"))
|
||||
.hasValue(Money.parse("USD 10"));
|
||||
assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "savant", "tld"))
|
||||
.hasValue(Money.parse("USD 90"));
|
||||
assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "dolt", "tld")).isEmpty();
|
||||
// TODO(b/79888775): Assert that the old premium list is enqueued for later deletion.
|
||||
assertThat(premiumListChecks)
|
||||
.hasValueForLabels(4, "tld", "tld", UNCACHED_POSITIVE.toString())
|
||||
|
@ -261,23 +234,22 @@ public class PremiumListUtilsTest {
|
|||
|
||||
@Test
|
||||
void testGetPremiumPrice_allLabelsAreNonPremium_whenNotInList() {
|
||||
assertThat(getPremiumPrice("blah", Registry.get("tld"))).isEmpty();
|
||||
assertThat(getPremiumPrice("slinge", Registry.get("tld"))).isEmpty();
|
||||
assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "blah", "tld")).isEmpty();
|
||||
assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "slinge", "tld")).isEmpty();
|
||||
assertMetricOutcomeCount(2, BLOOM_FILTER_NEGATIVE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSave_simple() {
|
||||
PremiumList pl =
|
||||
savePremiumListAndEntries(
|
||||
new PremiumList.Builder().setName("tld2").build(),
|
||||
ImmutableList.of("lol , USD 999 # yupper rooni "));
|
||||
createTld("tld");
|
||||
PremiumListDatastoreDao.save("tld2", ImmutableList.of("lol , USD 999 # yupper rooni "));
|
||||
persistResource(Registry.get("tld").asBuilder().setPremiumList(pl).build());
|
||||
assertThat(getPremiumPrice("lol", Registry.get("tld"))).hasValue(Money.parse("USD 999"));
|
||||
assertThat(getPremiumPrice("lol ", Registry.get("tld"))).isEmpty();
|
||||
assertThat(PremiumListDatastoreDao.getPremiumPrice("tld2", "lol", "tld"))
|
||||
.hasValue(Money.parse("USD 999"));
|
||||
assertThat(PremiumListDatastoreDao.getPremiumPrice("tld2", "lol ", "tld")).isEmpty();
|
||||
ImmutableMap<String, PremiumListEntry> entries =
|
||||
loadPremiumListEntries(PremiumList.getUncached("tld2").get());
|
||||
Streams.stream(PremiumListDatastoreDao.loadPremiumListEntriesUncached(pl))
|
||||
.collect(toImmutableMap(PremiumListEntry::getLabel, Function.identity()));
|
||||
assertThat(entries.keySet()).containsExactly("lol");
|
||||
assertThat(entries).doesNotContainKey("lol ");
|
||||
PremiumListEntry entry = entries.get("lol");
|
||||
|
@ -300,47 +272,47 @@ public class PremiumListUtilsTest {
|
|||
|
||||
@Test
|
||||
void test_saveAndUpdateEntriesTwice() {
|
||||
PremiumList pl =
|
||||
savePremiumListAndEntries(
|
||||
new PremiumList.Builder().setName("pl").build(), ImmutableList.of("test,USD 1"));
|
||||
ImmutableMap<String, PremiumListEntry> entries = loadPremiumListEntries(pl);
|
||||
PremiumList firstSave = PremiumListDatastoreDao.save("tld", ImmutableList.of("test,USD 1"));
|
||||
ImmutableMap<String, PremiumListEntry> entries =
|
||||
Streams.stream(PremiumListDatastoreDao.loadPremiumListEntriesUncached(firstSave))
|
||||
.collect(toImmutableMap(PremiumListEntry::getLabel, Function.identity()));
|
||||
assertThat(entries.keySet()).containsExactly("test");
|
||||
assertThat(loadPremiumListEntries(PremiumList.getUncached("pl").get())).isEqualTo(entries);
|
||||
// Save again with no changes, and clear the cache to force a re-load from Datastore.
|
||||
PremiumList resaved = savePremiumListAndEntries(pl, ImmutableList.of("test,USD 1"));
|
||||
PremiumList resaved = PremiumListDatastoreDao.save("tld", ImmutableList.of("test,USD 1"));
|
||||
ofy().clearSessionCache();
|
||||
Map<String, PremiumListEntry> entriesReloaded =
|
||||
loadPremiumListEntries(PremiumList.getUncached("pl").get());
|
||||
Streams.stream(PremiumListDatastoreDao.loadPremiumListEntriesUncached(resaved))
|
||||
.collect(toImmutableMap(PremiumListEntry::getLabel, Function.identity()));
|
||||
assertThat(entriesReloaded).hasSize(1);
|
||||
assertThat(entriesReloaded).containsKey("test");
|
||||
assertThat(entriesReloaded.get("test").parent).isEqualTo(resaved.getRevisionKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_savePremiumListAndEntries_clearsCache() {
|
||||
assertThat(PremiumList.cachePremiumLists.getIfPresent("tld")).isNull();
|
||||
PremiumList pl = PremiumList.getCached("tld").get();
|
||||
assertThat(PremiumList.cachePremiumLists.getIfPresent("tld")).isEqualTo(pl);
|
||||
savePremiumListAndEntries(
|
||||
new PremiumList.Builder().setName("tld").build(), ImmutableList.of("test,USD 1"));
|
||||
assertThat(PremiumList.cachePremiumLists.getIfPresent("tld")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDelete() {
|
||||
persistPremiumList("gtld1", "trombone,USD 10");
|
||||
assertThat(PremiumList.getUncached("gtld1")).isPresent();
|
||||
Key<PremiumListRevision> parent = PremiumList.getUncached("gtld1").get().getRevisionKey();
|
||||
deletePremiumList(PremiumList.getUncached("gtld1").get());
|
||||
assertThat(PremiumList.getUncached("gtld1")).isEmpty();
|
||||
Optional<PremiumList> gtld1 = PremiumListDatastoreDao.getLatestRevision("gtld1");
|
||||
assertThat(gtld1).isPresent();
|
||||
Key<PremiumListRevision> parent = gtld1.get().getRevisionKey();
|
||||
PremiumListDatastoreDao.delete(gtld1.get());
|
||||
assertThat(PremiumListDatastoreDao.getLatestRevision("gtld1")).isEmpty();
|
||||
assertThat(ofy().load().type(PremiumListEntry.class).ancestor(parent).list()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDelete_largeNumberOfEntries_succeeds() {
|
||||
persistHumongousPremiumList("ginormous", 2500);
|
||||
deletePremiumList(PremiumList.getUncached("ginormous").get());
|
||||
assertThat(PremiumList.getUncached("ginormous")).isEmpty();
|
||||
PremiumList large = persistHumongousPremiumList("ginormous", 2500);
|
||||
PremiumListDatastoreDao.delete(large);
|
||||
assertThat(PremiumListDatastoreDao.getLatestRevision("ginormous")).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_savePremiumList_clearsCache() {
|
||||
assertThat(PremiumListDatastoreDao.premiumListCache.getIfPresent("tld")).isNull();
|
||||
PremiumList pl = PremiumListDatastoreDao.getLatestRevision("tld").get();
|
||||
assertThat(PremiumListDatastoreDao.premiumListCache.getIfPresent("tld").get()).isEqualTo(pl);
|
||||
transactIfJpaTm(() -> PremiumListDatastoreDao.save("tld", ImmutableList.of("test,USD 1")));
|
||||
assertThat(PremiumListDatastoreDao.premiumListCache.getIfPresent("tld")).isNull();
|
||||
}
|
||||
|
||||
/** Persists a premium list with a specified number of nonsense entries. */
|
|
@ -0,0 +1,139 @@
|
|||
// Copyright 2021 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model.registry.label;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.newRegistry;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static org.joda.time.Duration.standardDays;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.truth.Truth8;
|
||||
import google.registry.dns.writer.VoidDnsWriter;
|
||||
import google.registry.model.pricing.StaticPremiumListPricingEngine;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.schema.tld.PremiumListSqlDao;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestCacheExtension;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import google.registry.testing.TestSqlOnly;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link PremiumListDualDao}. */
|
||||
@DualDatabaseTest
|
||||
public class PremiumListDualDaoTest {
|
||||
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withDatastoreAndCloudSql().build();
|
||||
|
||||
// Set long persist times on caches so they can be tested (cache times default to 0 in tests).
|
||||
@RegisterExtension
|
||||
public final TestCacheExtension testCacheExtension =
|
||||
new TestCacheExtension.Builder()
|
||||
.withPremiumListsCache(standardDays(1))
|
||||
.withPremiumListEntriesCache(standardDays(1))
|
||||
.build();
|
||||
|
||||
@BeforeEach
|
||||
void before() {
|
||||
createTld("tld");
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testGetPremiumPrice_secondaryLoadMissingSql() {
|
||||
PremiumListSqlDao.delete(PremiumListSqlDao.getLatestRevision("tld").get());
|
||||
assertThat(
|
||||
assertThrows(
|
||||
IllegalStateException.class,
|
||||
() -> PremiumListDualDao.getPremiumPrice("brass", Registry.get("tld"))))
|
||||
.hasMessageThat()
|
||||
.isEqualTo(
|
||||
"Unequal prices for domain brass.tld from primary Datastore DB "
|
||||
+ "(Optional[USD 20.00]) and secondary SQL db (Optional.empty).");
|
||||
}
|
||||
|
||||
@TestSqlOnly
|
||||
void testGetPremiumPrice_secondaryLoadMissingOfy() {
|
||||
PremiumList premiumList = PremiumListDatastoreDao.getLatestRevision("tld").get();
|
||||
PremiumListDatastoreDao.delete(premiumList);
|
||||
assertThat(
|
||||
assertThrows(
|
||||
IllegalStateException.class,
|
||||
() -> PremiumListDualDao.getPremiumPrice("brass", Registry.get("tld"))))
|
||||
.hasMessageThat()
|
||||
.isEqualTo(
|
||||
"Unequal prices for domain brass.tld from primary SQL DB (Optional[USD 20.00]) "
|
||||
+ "and secondary Datastore db (Optional.empty).");
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testGetPremiumPrice_secondaryDifferentSql() {
|
||||
PremiumListSqlDao.save("tld", ImmutableList.of("brass,USD 50"));
|
||||
assertThat(
|
||||
assertThrows(
|
||||
IllegalStateException.class,
|
||||
() -> PremiumListDualDao.getPremiumPrice("brass", Registry.get("tld"))))
|
||||
.hasMessageThat()
|
||||
.isEqualTo(
|
||||
"Unequal prices for domain brass.tld from primary Datastore DB "
|
||||
+ "(Optional[USD 20.00]) and secondary SQL db (Optional[USD 50.00]).");
|
||||
}
|
||||
|
||||
@TestSqlOnly
|
||||
void testGetPremiumPrice_secondaryDifferentOfy() {
|
||||
PremiumListDatastoreDao.save("tld", ImmutableList.of("brass,USD 50"));
|
||||
assertThat(
|
||||
assertThrows(
|
||||
IllegalStateException.class,
|
||||
() -> PremiumListDualDao.getPremiumPrice("brass", Registry.get("tld"))))
|
||||
.hasMessageThat()
|
||||
.isEqualTo(
|
||||
"Unequal prices for domain brass.tld from primary SQL DB "
|
||||
+ "(Optional[USD 20.00]) and secondary Datastore db (Optional[USD 50.00]).");
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testGetPremiumPrice_returnsNoPriceWhenNoPremiumListConfigured() {
|
||||
createTld("ghost");
|
||||
persistResource(
|
||||
new Registry.Builder()
|
||||
.setTldStr("ghost")
|
||||
.setPremiumPricingEngine(StaticPremiumListPricingEngine.NAME)
|
||||
.setDnsWriters(ImmutableSet.of(VoidDnsWriter.NAME))
|
||||
.build());
|
||||
assertThat(Registry.get("ghost").getPremiumList()).isNull();
|
||||
Truth8.assertThat(PremiumListDualDao.getPremiumPrice("blah", Registry.get("ghost"))).isEmpty();
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testGetPremiumPrice_emptyWhenPremiumListDeleted() {
|
||||
PremiumList toDelete = PremiumListDualDao.getLatestRevision("tld").get();
|
||||
PremiumListDualDao.delete(toDelete);
|
||||
Truth8.assertThat(PremiumListDualDao.getPremiumPrice("blah", Registry.get("tld"))).isEmpty();
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void getPremiumPrice_returnsNoneWhenNoPremiumListConfigured() {
|
||||
persistResource(newRegistry("foobar", "FOOBAR").asBuilder().setPremiumList(null).build());
|
||||
Truth8.assertThat(PremiumListDualDao.getPremiumPrice("rich", Registry.get("foobar"))).isEmpty();
|
||||
}
|
||||
}
|
|
@ -69,7 +69,7 @@ public class PremiumListTest {
|
|||
|
||||
@Test
|
||||
void testProbablePremiumLabels() {
|
||||
PremiumList pl = PremiumList.getUncached("tld").get();
|
||||
PremiumList pl = PremiumListDualDao.getLatestRevision("tld").get();
|
||||
PremiumListRevision revision = ofy().load().key(pl.getRevisionKey()).now();
|
||||
assertThat(revision.getProbablePremiumLabels().mightContain("notpremium")).isFalse();
|
||||
for (String label : ImmutableList.of("rich", "lol", "johnny-be-goode", "icann")) {
|
||||
|
@ -85,7 +85,7 @@ public class PremiumListTest {
|
|||
assertThrows(
|
||||
IllegalStateException.class,
|
||||
() ->
|
||||
PremiumList.getUncached("tld")
|
||||
PremiumListDualDao.getLatestRevision("tld")
|
||||
.get()
|
||||
.parse(
|
||||
ImmutableList.of(
|
||||
|
|
|
@ -42,7 +42,7 @@ import google.registry.schema.integration.SqlIntegrationTestSuite.BeforeSuiteTes
|
|||
import google.registry.schema.registrar.RegistrarDaoTest;
|
||||
import google.registry.schema.replay.SqlReplayCheckpointTest;
|
||||
import google.registry.schema.server.LockDaoTest;
|
||||
import google.registry.schema.tld.PremiumListDaoTest;
|
||||
import google.registry.schema.tld.PremiumListSqlDaoTest;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
|
@ -92,7 +92,7 @@ import org.junit.runner.RunWith;
|
|||
KmsSecretRevisionSqlDaoTest.class,
|
||||
LockDaoTest.class,
|
||||
PollMessageTest.class,
|
||||
PremiumListDaoTest.class,
|
||||
PremiumListSqlDaoTest.class,
|
||||
RdeRevisionTest.class,
|
||||
RegistrarDaoTest.class,
|
||||
RegistryTest.class,
|
||||
|
|
|
@ -18,30 +18,30 @@ import static com.google.common.truth.Truth.assertThat;
|
|||
import static com.google.common.truth.Truth8.assertThat;
|
||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.persistence.transaction.TransactionManagerUtil.transactIfJpaTm;
|
||||
import static google.registry.testing.DatabaseHelper.newRegistry;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static org.joda.money.CurrencyUnit.JPY;
|
||||
import static org.joda.money.CurrencyUnit.USD;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.joda.time.Duration.standardDays;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.model.registry.label.PremiumList;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.TestCacheExtension;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Optional;
|
||||
import org.joda.money.CurrencyUnit;
|
||||
import org.joda.money.Money;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link PremiumListDao}. */
|
||||
public class PremiumListDaoTest {
|
||||
/** Unit tests for {@link PremiumListSqlDao}. */
|
||||
public class PremiumListSqlDaoTest {
|
||||
|
||||
private final FakeClock fakeClock = new FakeClock();
|
||||
|
||||
|
@ -53,6 +53,14 @@ public class PremiumListDaoTest {
|
|||
.withClock(fakeClock)
|
||||
.build();
|
||||
|
||||
// Set long persist times on caches so they can be tested (cache times default to 0 in tests).
|
||||
@RegisterExtension
|
||||
public final TestCacheExtension testCacheExtension =
|
||||
new TestCacheExtension.Builder()
|
||||
.withPremiumListsCache(standardDays(1))
|
||||
.withPremiumListEntriesCache(standardDays(1))
|
||||
.build();
|
||||
|
||||
private ImmutableMap<String, BigDecimal> testPrices;
|
||||
|
||||
private PremiumList testList;
|
||||
|
@ -78,11 +86,12 @@ public class PremiumListDaoTest {
|
|||
|
||||
@Test
|
||||
void saveNew_worksSuccessfully() {
|
||||
PremiumListDao.saveNew(testList);
|
||||
PremiumListSqlDao.save(testList);
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
Optional<PremiumList> persistedListOpt = PremiumListDao.getLatestRevision("testname");
|
||||
Optional<PremiumList> persistedListOpt =
|
||||
PremiumListSqlDao.getLatestRevision("testname");
|
||||
assertThat(persistedListOpt).isPresent();
|
||||
PremiumList persistedList = persistedListOpt.get();
|
||||
assertThat(persistedList.getLabelsToPrices()).containsExactlyEntriesIn(testPrices);
|
||||
|
@ -92,17 +101,17 @@ public class PremiumListDaoTest {
|
|||
|
||||
@Test
|
||||
void update_worksSuccessfully() {
|
||||
PremiumListDao.saveNew(testList);
|
||||
Optional<PremiumList> persistedList = PremiumListDao.getLatestRevision("testname");
|
||||
PremiumListSqlDao.save(testList);
|
||||
Optional<PremiumList> persistedList = PremiumListSqlDao.getLatestRevision("testname");
|
||||
assertThat(persistedList).isPresent();
|
||||
long firstRevisionId = persistedList.get().getRevisionId();
|
||||
PremiumListDao.update(
|
||||
PremiumListSqlDao.save(
|
||||
new PremiumList.Builder()
|
||||
.setName("testname")
|
||||
.setCurrency(USD)
|
||||
.setLabelsToPrices(
|
||||
ImmutableMap.of(
|
||||
"update",
|
||||
"save",
|
||||
BigDecimal.valueOf(55343.12),
|
||||
"new",
|
||||
BigDecimal.valueOf(0.01),
|
||||
|
@ -113,65 +122,46 @@ public class PremiumListDaoTest {
|
|||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
Optional<PremiumList> updatedListOpt = PremiumListDao.getLatestRevision("testname");
|
||||
assertThat(updatedListOpt).isPresent();
|
||||
PremiumList updatedList = updatedListOpt.get();
|
||||
assertThat(updatedList.getLabelsToPrices())
|
||||
Optional<PremiumList> savedListOpt = PremiumListSqlDao.getLatestRevision("testname");
|
||||
assertThat(savedListOpt).isPresent();
|
||||
PremiumList savedList = savedListOpt.get();
|
||||
assertThat(savedList.getLabelsToPrices())
|
||||
.containsExactlyEntriesIn(
|
||||
ImmutableMap.of(
|
||||
"update",
|
||||
"save",
|
||||
BigDecimal.valueOf(55343.12),
|
||||
"new",
|
||||
BigDecimal.valueOf(0.01),
|
||||
"silver",
|
||||
BigDecimal.valueOf(30.03)));
|
||||
assertThat(updatedList.getCreationTime()).isEqualTo(fakeClock.nowUtc());
|
||||
assertThat(updatedList.getRevisionId()).isGreaterThan(firstRevisionId);
|
||||
assertThat(updatedList.getCreationTime()).isEqualTo(fakeClock.nowUtc());
|
||||
assertThat(savedList.getCreationTime()).isEqualTo(fakeClock.nowUtc());
|
||||
assertThat(savedList.getRevisionId()).isGreaterThan(firstRevisionId);
|
||||
assertThat(savedList.getCreationTime()).isEqualTo(fakeClock.nowUtc());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveNew_throwsWhenPremiumListAlreadyExists() {
|
||||
PremiumListDao.saveNew(testList);
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(IllegalArgumentException.class, () -> PremiumListDao.saveNew(testList));
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("Premium list 'testname' already exists");
|
||||
}
|
||||
|
||||
// TODO(b/147246613): Un-ignore this.
|
||||
@Test
|
||||
@Disabled
|
||||
void update_throwsWhenListDoesntExist() {
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(IllegalArgumentException.class, () -> PremiumListDao.update(testList));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Can't update non-existent premium list 'testname'");
|
||||
}
|
||||
|
||||
@Test
|
||||
void checkExists_worksSuccessfully() {
|
||||
assertThat(PremiumListDao.checkExists("testname")).isFalse();
|
||||
PremiumListDao.saveNew(testList);
|
||||
assertThat(PremiumListDao.checkExists("testname")).isTrue();
|
||||
assertThat(PremiumListSqlDao.getLatestRevision("testname")).isEmpty();
|
||||
PremiumListSqlDao.save(testList);
|
||||
assertThat(PremiumListSqlDao.getLatestRevision("testname")).isPresent();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getLatestRevision_returnsEmptyForNonexistentList() {
|
||||
assertThat(PremiumListDao.getLatestRevision("nonexistentlist")).isEmpty();
|
||||
assertThat(PremiumListSqlDao.getLatestRevision("nonexistentlist")).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getLatestRevision_worksSuccessfully() {
|
||||
PremiumListDao.saveNew(
|
||||
PremiumListSqlDao.save(
|
||||
new PremiumList.Builder()
|
||||
.setName("list1")
|
||||
.setCurrency(JPY)
|
||||
.setLabelsToPrices(ImmutableMap.of("wrong", BigDecimal.valueOf(1000.50)))
|
||||
.setCreationTime(fakeClock.nowUtc())
|
||||
.build());
|
||||
PremiumListDao.update(
|
||||
PremiumListSqlDao.save(
|
||||
new PremiumList.Builder()
|
||||
.setName("list1")
|
||||
.setCurrency(JPY)
|
||||
|
@ -181,7 +171,7 @@ public class PremiumListDaoTest {
|
|||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
Optional<PremiumList> persistedList = PremiumListDao.getLatestRevision("list1");
|
||||
Optional<PremiumList> persistedList = PremiumListSqlDao.getLatestRevision("list1");
|
||||
assertThat(persistedList).isPresent();
|
||||
assertThat(persistedList.get().getName()).isEqualTo("list1");
|
||||
assertThat(persistedList.get().getCurrency()).isEqualTo(JPY);
|
||||
|
@ -190,12 +180,6 @@ public class PremiumListDaoTest {
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void getPremiumPrice_returnsNoneWhenNoPremiumListConfigured() {
|
||||
persistResource(newRegistry("foobar", "FOOBAR").asBuilder().setPremiumList(null).build());
|
||||
assertThat(PremiumListDao.getPremiumPrice("rich", Registry.get("foobar"))).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getPremiumPrice_worksSuccessfully() {
|
||||
persistResource(
|
||||
|
@ -207,28 +191,18 @@ public class PremiumListDaoTest {
|
|||
google.registry.model.registry.label.PremiumList.class,
|
||||
"premlist"))
|
||||
.build());
|
||||
PremiumListDao.saveNew(
|
||||
PremiumListSqlDao.save(
|
||||
new PremiumList.Builder()
|
||||
.setName("premlist")
|
||||
.setCurrency(USD)
|
||||
.setLabelsToPrices(testPrices)
|
||||
.setCreationTime(fakeClock.nowUtc())
|
||||
.build());
|
||||
assertThat(PremiumListDao.getPremiumPrice("silver", Registry.get("foobar")))
|
||||
assertThat(PremiumListSqlDao.getPremiumPrice("premlist", "silver"))
|
||||
.hasValue(Money.of(USD, 10.23));
|
||||
assertThat(PremiumListDao.getPremiumPrice("gold", Registry.get("foobar")))
|
||||
assertThat(PremiumListSqlDao.getPremiumPrice("premlist", "gold"))
|
||||
.hasValue(Money.of(USD, 1305.47));
|
||||
assertThat(PremiumListDao.getPremiumPrice("zirconium", Registry.get("foobar"))).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetPremiumPrice_throwsWhenPremiumListCantBeLoaded() {
|
||||
createTld("tld");
|
||||
IllegalStateException thrown =
|
||||
assertThrows(
|
||||
IllegalStateException.class,
|
||||
() -> PremiumListDao.getPremiumPrice("foobar", Registry.get("tld")));
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("Could not load premium list 'tld'");
|
||||
assertThat(PremiumListSqlDao.getPremiumPrice("premlist", "zirconium")).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -242,7 +216,7 @@ public class PremiumListDaoTest {
|
|||
google.registry.model.registry.label.PremiumList.class,
|
||||
"premlist"))
|
||||
.build());
|
||||
PremiumListDao.saveNew(
|
||||
PremiumListSqlDao.save(
|
||||
new PremiumList.Builder()
|
||||
.setName("premlist")
|
||||
.setCurrency(JPY)
|
||||
|
@ -256,14 +230,22 @@ public class PremiumListDaoTest {
|
|||
BigDecimal.valueOf(15000)))
|
||||
.setCreationTime(fakeClock.nowUtc())
|
||||
.build());
|
||||
assertThat(PremiumListDao.getPremiumPrice("silver", Registry.get("foobar")))
|
||||
.hasValue(moneyOf(JPY, 10));
|
||||
assertThat(PremiumListDao.getPremiumPrice("gold", Registry.get("foobar")))
|
||||
.hasValue(moneyOf(JPY, 1000));
|
||||
assertThat(PremiumListDao.getPremiumPrice("palladium", Registry.get("foobar")))
|
||||
assertThat(PremiumListSqlDao.getPremiumPrice("premlist", "silver")).hasValue(moneyOf(JPY, 10));
|
||||
assertThat(PremiumListSqlDao.getPremiumPrice("premlist", "gold")).hasValue(moneyOf(JPY, 1000));
|
||||
assertThat(PremiumListSqlDao.getPremiumPrice("premlist", "palladium"))
|
||||
.hasValue(moneyOf(JPY, 15000));
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_savePremiumList_clearsCache() {
|
||||
assertThat(PremiumListSqlDao.premiumListCache.getIfPresent("testname")).isNull();
|
||||
PremiumListSqlDao.save(testList);
|
||||
PremiumList pl = PremiumListSqlDao.getLatestRevision("testname").get();
|
||||
assertThat(PremiumListSqlDao.premiumListCache.getIfPresent("testname").get()).isEqualTo(pl);
|
||||
transactIfJpaTm(() -> PremiumListSqlDao.save("testname", ImmutableList.of("test,USD 1")));
|
||||
assertThat(PremiumListSqlDao.premiumListCache.getIfPresent("testname")).isNull();
|
||||
}
|
||||
|
||||
private static Money moneyOf(CurrencyUnit unit, double amount) {
|
||||
return Money.of(unit, BigDecimal.valueOf(amount).setScale(unit.getDecimalPlaces()));
|
||||
}
|
|
@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assertThat;
|
|||
import static google.registry.schema.tld.PremiumListUtils.parseToPremiumList;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.model.registry.label.PremiumList;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import java.math.BigDecimal;
|
||||
|
@ -34,7 +35,8 @@ class PremiumListUtilsTest {
|
|||
@Test
|
||||
void parseInputToPremiumList_works() {
|
||||
PremiumList premiumList =
|
||||
parseToPremiumList("testlist", "foo,USD 99.50\n" + "bar,USD 30\n" + "baz,USD 10\n");
|
||||
parseToPremiumList(
|
||||
"testlist", ImmutableList.of("foo,USD 99.50", "bar,USD 30", "baz,USD 10"));
|
||||
assertThat(premiumList.getName()).isEqualTo("testlist");
|
||||
assertThat(premiumList.getLabelsToPrices())
|
||||
.containsExactly("foo", twoDigits(99.50), "bar", twoDigits(30), "baz", twoDigits(10));
|
||||
|
@ -47,7 +49,7 @@ class PremiumListUtilsTest {
|
|||
IllegalArgumentException.class,
|
||||
() ->
|
||||
parseToPremiumList(
|
||||
"testlist", "foo,USD 99.50\n" + "bar,USD 30\n" + "baz,JPY 990\n"));
|
||||
"testlist", ImmutableList.of("foo,USD 99.50", "bar,USD 30", "baz,JPY 990")));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.isEqualTo("The Cloud SQL schema requires exactly one currency, but got: [JPY, USD]");
|
||||
|
|
|
@ -32,7 +32,9 @@ import static google.registry.model.ImmutableObjectSubject.immutableObjectCorres
|
|||
import static google.registry.model.ResourceTransferUtils.createTransferResponse;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.registry.Registry.TldState.GENERAL_AVAILABILITY;
|
||||
import static google.registry.model.registry.label.PremiumListUtils.parentPremiumListEntriesOnRevision;
|
||||
import static google.registry.model.registry.label.PremiumListDatastoreDao.parentPremiumListEntriesOnRevision;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.ofyTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerUtil.ofyTmOrDoNothing;
|
||||
import static google.registry.persistence.transaction.TransactionManagerUtil.transactIfJpaTm;
|
||||
|
@ -57,6 +59,7 @@ import com.google.common.collect.ImmutableMap;
|
|||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.common.net.InetAddresses;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.cmd.Saver;
|
||||
|
@ -100,6 +103,7 @@ import google.registry.model.registry.Registry.TldType;
|
|||
import google.registry.model.registry.label.PremiumList;
|
||||
import google.registry.model.registry.label.PremiumList.PremiumListEntry;
|
||||
import google.registry.model.registry.label.PremiumList.PremiumListRevision;
|
||||
import google.registry.model.registry.label.PremiumListDualDao;
|
||||
import google.registry.model.registry.label.ReservedList;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.transfer.ContactTransferData;
|
||||
|
@ -108,11 +112,11 @@ import google.registry.model.transfer.TransferData;
|
|||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.tmch.LordnTaskUtils;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import javax.annotation.Nullable;
|
||||
import org.joda.money.CurrencyUnit;
|
||||
import org.joda.money.Money;
|
||||
|
@ -387,25 +391,23 @@ public class DatabaseHelper {
|
|||
.build();
|
||||
PremiumListRevision revision = PremiumListRevision.create(premiumList, entries.keySet());
|
||||
|
||||
if (tm().isOfy()) {
|
||||
ImmutableList<Object> premiumLists =
|
||||
ImmutableList.of(
|
||||
premiumList.asBuilder().setRevision(Key.create(revision)).build(), revision);
|
||||
ImmutableSet<PremiumListEntry> entriesOnRevision =
|
||||
parentPremiumListEntriesOnRevision(entries.values(), Key.create(revision));
|
||||
if (alwaysSaveWithBackup) {
|
||||
tm().transact(
|
||||
() -> {
|
||||
tm().putAll(premiumLists);
|
||||
tm().putAll(entriesOnRevision);
|
||||
});
|
||||
} else {
|
||||
tm().putAllWithoutBackup(premiumLists);
|
||||
tm().putAllWithoutBackup(entriesOnRevision);
|
||||
}
|
||||
ImmutableList<Object> premiumListOfyObjects =
|
||||
ImmutableList.of(
|
||||
premiumList.asBuilder().setRevision(Key.create(revision)).build(), revision);
|
||||
ImmutableSet<PremiumListEntry> entriesOnRevision =
|
||||
parentPremiumListEntriesOnRevision(entries.values(), Key.create(revision));
|
||||
if (alwaysSaveWithBackup) {
|
||||
ofyTm()
|
||||
.transact(
|
||||
() -> {
|
||||
ofyTm().putAll(premiumListOfyObjects);
|
||||
ofyTm().putAll(entriesOnRevision);
|
||||
});
|
||||
} else {
|
||||
tm().transact(() -> tm().insert(premiumList));
|
||||
ofyTm().putAllWithoutBackup(premiumListOfyObjects);
|
||||
ofyTm().putAllWithoutBackup(entriesOnRevision);
|
||||
}
|
||||
jpaTm().transact(() -> jpaTm().insert(premiumList));
|
||||
maybeAdvanceClock();
|
||||
// The above premiumList is in the session cache and it is different from the corresponding
|
||||
// entity stored in Datastore because it has some @Ignore fields set dedicated for SQL. This
|
||||
|
@ -807,7 +809,7 @@ public class DatabaseHelper {
|
|||
|
||||
/** Assert that the expected billing events are exactly the ones found in the fake Datastore. */
|
||||
public static void assertBillingEvents(BillingEvent... expected) {
|
||||
assertBillingEventsEqual(getBillingEvents(), Arrays.asList(expected));
|
||||
assertBillingEventsEqual(getBillingEvents(), asList(expected));
|
||||
}
|
||||
|
||||
/** Assert that the expected billing events set is exactly the one found in the fake Datastore. */
|
||||
|
@ -820,7 +822,7 @@ public class DatabaseHelper {
|
|||
*/
|
||||
public static void assertBillingEventsForResource(
|
||||
EppResource resource, BillingEvent... expected) {
|
||||
assertBillingEventsEqual(getBillingEvents(resource), Arrays.asList(expected));
|
||||
assertBillingEventsEqual(getBillingEvents(resource), asList(expected));
|
||||
}
|
||||
|
||||
/** Assert that there are no billing events. */
|
||||
|
@ -851,15 +853,15 @@ public class DatabaseHelper {
|
|||
}
|
||||
|
||||
public static void assertPollMessages(String clientId, PollMessage... expected) {
|
||||
assertPollMessagesEqual(getPollMessages(clientId), Arrays.asList(expected));
|
||||
assertPollMessagesEqual(getPollMessages(clientId), asList(expected));
|
||||
}
|
||||
|
||||
public static void assertPollMessages(PollMessage... expected) {
|
||||
assertPollMessagesEqual(getPollMessages(), Arrays.asList(expected));
|
||||
assertPollMessagesEqual(getPollMessages(), asList(expected));
|
||||
}
|
||||
|
||||
public static void assertPollMessagesForResource(DomainContent domain, PollMessage... expected) {
|
||||
assertPollMessagesEqual(getPollMessages(domain), Arrays.asList(expected));
|
||||
assertPollMessagesEqual(getPollMessages(domain), asList(expected));
|
||||
}
|
||||
|
||||
public static ImmutableList<PollMessage> getPollMessages() {
|
||||
|
@ -1232,19 +1234,8 @@ public class DatabaseHelper {
|
|||
/** Returns the entire map of {@link PremiumListEntry}s for the given {@link PremiumList}. */
|
||||
public static ImmutableMap<String, PremiumListEntry> loadPremiumListEntries(
|
||||
PremiumList premiumList) {
|
||||
try {
|
||||
ImmutableMap.Builder<String, PremiumListEntry> entriesMap = new ImmutableMap.Builder<>();
|
||||
if (premiumList.getRevisionKey() != null) {
|
||||
for (PremiumListEntry entry :
|
||||
ofy().load().type(PremiumListEntry.class).ancestor(premiumList.getRevisionKey())) {
|
||||
entriesMap.put(entry.getLabel(), entry);
|
||||
}
|
||||
}
|
||||
return entriesMap.build();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(
|
||||
"Could not retrieve entries for premium list " + premiumList.getName(), e);
|
||||
}
|
||||
return Streams.stream(PremiumListDualDao.loadAllPremiumListEntries(premiumList.getName()))
|
||||
.collect(toImmutableMap(PremiumListEntry::getLabel, Function.identity()));
|
||||
}
|
||||
|
||||
/** Loads and returns the registrar with the given client ID, or throws IAE if not present. */
|
||||
|
|
|
@ -18,7 +18,8 @@ import com.google.common.collect.ImmutableList;
|
|||
import com.google.common.collect.Maps;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.index.ForeignKeyIndex;
|
||||
import google.registry.model.registry.label.PremiumList;
|
||||
import google.registry.model.registry.label.PremiumListDatastoreDao;
|
||||
import google.registry.schema.tld.PremiumListSqlDao;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import org.joda.time.Duration;
|
||||
|
@ -70,15 +71,18 @@ public class TestCacheExtension implements BeforeEachCallback, AfterEachCallback
|
|||
|
||||
public Builder withPremiumListsCache(Duration expiry) {
|
||||
cacheHandlerMap.put(
|
||||
"PremiumList.cachePremiumLists",
|
||||
new TestCacheHandler(PremiumList::setPremiumListCacheForTest, expiry));
|
||||
"PremiumListSqlDao.premiumListCache",
|
||||
new TestCacheHandler(PremiumListSqlDao::setPremiumListCacheForTest, expiry));
|
||||
cacheHandlerMap.put(
|
||||
"PremiumListDatastoreDao.premiumListCache",
|
||||
new TestCacheHandler(PremiumListDatastoreDao::setPremiumListCacheForTest, expiry));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withPremiumListEntriesCache(Duration expiry) {
|
||||
cacheHandlerMap.put(
|
||||
"PremiumList.cachePremiumListEntries",
|
||||
new TestCacheHandler(PremiumList::setPremiumListEntriesCacheForTest, expiry));
|
||||
new TestCacheHandler(PremiumListDatastoreDao::setPremiumListEntriesCacheForTest, expiry));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
|||
|
||||
import com.beust.jcommander.ParameterException;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.model.registry.label.PremiumList;
|
||||
import google.registry.model.registry.label.PremiumListDualDao;
|
||||
import google.registry.testing.DeterministicStringGenerator;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -101,7 +101,7 @@ class CreateDomainCommandTest extends EppToolCommandTestCase<CreateDomainCommand
|
|||
persistResource(
|
||||
Registry.get("baar")
|
||||
.asBuilder()
|
||||
.setPremiumList(PremiumList.getUncached("baar").get())
|
||||
.setPremiumList(PremiumListDualDao.getLatestRevision("baar").get())
|
||||
.build());
|
||||
runCommandForced(
|
||||
"--client=NewRegistrar",
|
||||
|
|
|
@ -26,6 +26,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
|||
import google.registry.model.registry.Registry;
|
||||
import google.registry.model.registry.label.PremiumList;
|
||||
import google.registry.model.registry.label.PremiumList.PremiumListEntry;
|
||||
import google.registry.model.registry.label.PremiumListDualDao;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link DeletePremiumListCommand}. */
|
||||
|
@ -36,7 +37,7 @@ class DeletePremiumListCommandTest extends CommandTestCase<DeletePremiumListComm
|
|||
PremiumList premiumList = persistPremiumList("xn--q9jyb4c", "blah,USD 100");
|
||||
assertThat(loadPremiumListEntries(premiumList)).hasSize(1);
|
||||
runCommand("--force", "--name=xn--q9jyb4c");
|
||||
assertThat(PremiumList.getUncached("xn--q9jyb4c")).isEmpty();
|
||||
assertThat(PremiumListDualDao.getLatestRevision("xn--q9jyb4c")).isEmpty();
|
||||
|
||||
// Ensure that the Datastore premium list entry entities were deleted correctly.
|
||||
assertThat(ofy().load()
|
||||
|
@ -64,7 +65,7 @@ class DeletePremiumListCommandTest extends CommandTestCase<DeletePremiumListComm
|
|||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> runCommandForced("--name=" + premiumList.getName()));
|
||||
assertThat(PremiumList.getUncached(premiumList.getName())).isPresent();
|
||||
assertThat(PremiumListDualDao.getLatestRevision(premiumList.getName())).isPresent();
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Cannot delete premium list because it is used on these tld(s): xn--q9jyb4c");
|
||||
|
|
|
@ -16,14 +16,13 @@ package google.registry.tools.server;
|
|||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth8.assertThat;
|
||||
import static google.registry.model.registry.label.PremiumListUtils.deletePremiumList;
|
||||
import static google.registry.model.registry.label.PremiumListUtils.getPremiumPrice;
|
||||
import static google.registry.testing.DatabaseHelper.createTlds;
|
||||
import static google.registry.testing.DatabaseHelper.loadPremiumListEntries;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.model.registry.label.PremiumList;
|
||||
import google.registry.model.registry.label.PremiumListDualDao;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeJsonResponse;
|
||||
import org.joda.money.Money;
|
||||
|
@ -46,7 +45,7 @@ public class CreatePremiumListActionTest {
|
|||
@BeforeEach
|
||||
void beforeEach() {
|
||||
createTlds("foo", "xn--q9jyb4c", "how");
|
||||
deletePremiumList(PremiumList.getUncached("foo").get());
|
||||
PremiumListDualDao.delete(PremiumListDualDao.getLatestRevision("foo").get());
|
||||
action = new CreatePremiumListAction();
|
||||
response = new FakeJsonResponse();
|
||||
action.response = response;
|
||||
|
@ -78,7 +77,8 @@ public class CreatePremiumListActionTest {
|
|||
action.override = true;
|
||||
action.run();
|
||||
assertThat(response.getStatus()).isEqualTo(SC_OK);
|
||||
assertThat(loadPremiumListEntries(PremiumList.getUncached("zanzibar").get())).hasSize(1);
|
||||
assertThat(loadPremiumListEntries(PremiumListDualDao.getLatestRevision("zanzibar").get()))
|
||||
.hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -87,8 +87,10 @@ public class CreatePremiumListActionTest {
|
|||
action.inputData = "rich,USD 25\nricher,USD 1000\n";
|
||||
action.run();
|
||||
assertThat(response.getStatus()).isEqualTo(SC_OK);
|
||||
assertThat(loadPremiumListEntries(PremiumList.getUncached("foo").get())).hasSize(2);
|
||||
assertThat(getPremiumPrice("rich", Registry.get("foo"))).hasValue(Money.parse("USD 25"));
|
||||
assertThat(getPremiumPrice("diamond", Registry.get("foo"))).isEmpty();
|
||||
PremiumList premiumList = PremiumListDualDao.getLatestRevision("foo").get();
|
||||
assertThat(loadPremiumListEntries(premiumList)).hasSize(2);
|
||||
assertThat(PremiumListDualDao.getPremiumPrice("rich", Registry.get("foo")))
|
||||
.hasValue(Money.parse("USD 25"));
|
||||
assertThat(PremiumListDualDao.getPremiumPrice("diamond", Registry.get("foo"))).isEmpty();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,22 +15,23 @@
|
|||
package google.registry.tools.server;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth8.assertThat;
|
||||
import static google.registry.model.registry.label.PremiumListUtils.getPremiumPrice;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.schema.tld.PremiumListUtils.parseToPremiumList;
|
||||
import static google.registry.testing.DatabaseHelper.createTlds;
|
||||
import static google.registry.testing.DatabaseHelper.loadPremiumListEntries;
|
||||
import static google.registry.util.ResourceUtils.readResourceUtf8;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.truth.Truth8;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.model.registry.label.PremiumList;
|
||||
import google.registry.schema.tld.PremiumListDao;
|
||||
import google.registry.model.registry.label.PremiumListDualDao;
|
||||
import google.registry.schema.tld.PremiumListSqlDao;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.FakeJsonResponse;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import org.joda.money.Money;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -75,24 +76,31 @@ class UpdatePremiumListActionTest {
|
|||
|
||||
@Test
|
||||
void test_success() {
|
||||
PremiumListDao.saveNew(
|
||||
parseToPremiumList(
|
||||
"foo", readResourceUtf8(DatabaseHelper.class, "default_premium_list_testdata.csv")));
|
||||
List<String> inputLines =
|
||||
Splitter.on('\n')
|
||||
.omitEmptyStrings()
|
||||
.splitToList(
|
||||
readResourceUtf8(DatabaseHelper.class, "default_premium_list_testdata.csv"));
|
||||
PremiumListDualDao.save("foo", inputLines);
|
||||
action.name = "foo";
|
||||
action.inputData = "rich,USD 75\nricher,USD 5000\npoor, USD 0.99";
|
||||
action.run();
|
||||
assertThat(response.getStatus()).isEqualTo(SC_OK);
|
||||
Registry registry = Registry.get("foo");
|
||||
assertThat(loadPremiumListEntries(PremiumList.getUncached("foo").get())).hasSize(3);
|
||||
assertThat(getPremiumPrice("rich", registry)).hasValue(Money.parse("USD 75"));
|
||||
assertThat(getPremiumPrice("richer", registry)).hasValue(Money.parse("USD 5000"));
|
||||
assertThat(getPremiumPrice("poor", registry)).hasValue(Money.parse("USD 0.99"));
|
||||
assertThat(getPremiumPrice("diamond", registry)).isEmpty();
|
||||
assertThat(loadPremiumListEntries(PremiumListDualDao.getLatestRevision("foo").get()))
|
||||
.hasSize(3);
|
||||
Truth8.assertThat(PremiumListDualDao.getPremiumPrice("rich", registry))
|
||||
.hasValue(Money.parse("USD 75"));
|
||||
Truth8.assertThat(PremiumListDualDao.getPremiumPrice("richer", registry))
|
||||
.hasValue(Money.parse("USD 5000"));
|
||||
Truth8.assertThat(PremiumListDualDao.getPremiumPrice("poor", registry))
|
||||
.hasValue(Money.parse("USD 0.99"));
|
||||
Truth8.assertThat(PremiumListDualDao.getPremiumPrice("diamond", registry)).isEmpty();
|
||||
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
PremiumList persistedList = PremiumListDao.getLatestRevision("foo").get();
|
||||
PremiumList persistedList = PremiumListSqlDao.getLatestRevision("foo").get();
|
||||
assertThat(persistedList.getLabelsToPrices())
|
||||
.containsEntry("rich", new BigDecimal("75.00"));
|
||||
assertThat(persistedList.getLabelsToPrices())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue