Stop writing PremiumList to Datastore (#1160)

* Stop writing PremiumList to Datastore

* Fix formatting

* Format fix

* Rename the DAO

* Fix merge conflicts and add comment
This commit is contained in:
sarahcaseybot
2021-05-14 16:13:05 -04:00
committed by GitHub
parent e09138645f
commit 93dc812ea2
34 changed files with 142 additions and 1295 deletions
@@ -37,8 +37,8 @@ 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.schema.tld.PremiumListDao;
import google.registry.storage.drive.DriveConnection;
import google.registry.testing.AppEngineExtension;
import java.io.IOException;
@@ -75,7 +75,7 @@ public class ExportPremiumTermsActionTest {
@BeforeEach
void beforeEach() throws Exception {
createTld("tld");
PremiumList pl = PremiumListDualDao.save("pl-name", PREMIUM_NAMES);
PremiumList pl = PremiumListDao.save("pl-name", PREMIUM_NAMES);
persistResource(
Registry.get("tld").asBuilder().setPremiumList(pl).setDriveFolderId("folder_id").build());
when(driveConnection.createOrUpdateFile(
@@ -143,7 +143,7 @@ public class ExportPremiumTermsActionTest {
@Test
void test_exportPremiumTerms_failure_noPremiumList() {
PremiumListDualDao.delete(new PremiumList.Builder().setName("pl-name").build());
PremiumListDao.delete(new PremiumList.Builder().setName("pl-name").build());
assertThrows(RuntimeException.class, () -> runAction("tld"));
verifyNoInteractions(driveConnection);
@@ -42,8 +42,8 @@ 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.schema.tld.PremiumListDao;
import google.registry.testing.DatabaseHelper;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.TestOfyAndSql;
@@ -251,7 +251,7 @@ public final class RegistryTest extends EntityTestCase {
Registry registry = Registry.get("tld").asBuilder().setPremiumList(pl2).build();
Key<PremiumList> plKey = registry.getPremiumList();
assertThat(plKey).isNotNull();
PremiumList stored = PremiumListDualDao.getLatestRevision(plKey.getName()).get();
PremiumList stored = PremiumListDao.getLatestRevision(plKey.getName()).get();
assertThat(stored.getName()).isEqualTo("tld2");
}
@@ -1,326 +0,0 @@
// Copyright 2017 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.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;
import static com.google.monitoring.metrics.contrib.LongMetricSubject.assertThat;
import static google.registry.model.ofy.ObjectifyService.auditedOfy;
import static google.registry.model.registry.label.DomainLabelMetrics.PremiumListCheckOutcome.BLOOM_FILTER_NEGATIVE;
import static google.registry.model.registry.label.DomainLabelMetrics.PremiumListCheckOutcome.CACHED_NEGATIVE;
import static google.registry.model.registry.label.DomainLabelMetrics.PremiumListCheckOutcome.CACHED_POSITIVE;
import static google.registry.model.registry.label.DomainLabelMetrics.PremiumListCheckOutcome.UNCACHED_NEGATIVE;
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.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 com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Streams;
import com.googlecode.objectify.Key;
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 PremiumListDatastoreDao}. */
public class PremiumListDatastoreDaoTest {
@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();
private PremiumList pl;
@BeforeEach
void before() {
// createTld() overwrites the premium list, so call it before persisting pl.
createTld("tld");
pl =
persistPremiumList(
"tld",
"lol,USD 999 # yup",
"rich,USD 1999 #tada",
"icann,JPY 100",
"johnny-be-goode,USD 20.50");
persistResource(Registry.get("tld").asBuilder().setPremiumList(pl).build());
premiumListChecks.reset();
premiumListProcessingTime.reset();
}
void assertMetricOutcomeCount(
int checkCount, DomainLabelMetrics.PremiumListCheckOutcome outcome) {
assertThat(premiumListChecks)
.hasValueForLabels(checkCount, "tld", "tld", outcome.toString())
.and()
.hasNoOtherValues();
assertThat(premiumListProcessingTime)
.hasAnyValueForLabels("tld", "tld", outcome.toString())
.and()
.hasNoOtherValues();
}
@Test
void testSave_largeNumberOfEntries_succeeds() {
PremiumList premiumList = persistHumongousPremiumList("tld", 2500);
assertThat(loadPremiumListEntries(premiumList)).hasSize(2500);
assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "7", "tld"))
.hasValue(Money.parse("USD 100"));
assertMetricOutcomeCount(1, UNCACHED_POSITIVE);
}
@Test
void testSave_updateTime_isUpdatedOnEverySave() {
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 =
PremiumListDatastoreDao.save("tld3", ImmutableList.of("sleighbells,CHF 2000"));
assertThat(newPl.creationTime).isEqualTo(pl.creationTime);
}
@Test
void testExists() {
assertThat(PremiumListDatastoreDao.getLatestRevision("tld")).isPresent();
assertThat(PremiumListDatastoreDao.getLatestRevision("nonExistentPremiumList")).isEmpty();
}
@Test
void testGetPremiumPrice_comesFromBloomFilter() throws Exception {
PremiumList pl = PremiumListDatastoreDao.getLatestRevision("tld").get();
PremiumListEntry entry =
persistResource(
new PremiumListEntry.Builder()
.setParent(pl.getRevisionKey())
.setLabel("missingno")
.setPrice(Money.parse("USD 1000"))
.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(PremiumListDatastoreDao.getPremiumPrice("tld", "missingno", "tld")).isEmpty();
// However, if we manually query the cache to force an entity load, it should be found.
assertThat(
PremiumListDatastoreDao.premiumListEntriesCache.get(
Key.create(pl.getRevisionKey(), PremiumListEntry.class, "missingno")))
.hasValue(entry);
assertMetricOutcomeCount(1, BLOOM_FILTER_NEGATIVE);
}
@Test
void testGetPremiumPrice_cachedSecondTime() {
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()
.hasValueForLabels(1, "tld", "tld", CACHED_POSITIVE.toString())
.and()
.hasNoOtherValues();
assertThat(premiumListProcessingTime)
.hasAnyValueForLabels("tld", "tld", UNCACHED_POSITIVE.toString())
.and()
.hasAnyValueForLabels("tld", "tld", CACHED_POSITIVE.toString())
.and()
.hasNoOtherValues();
}
@Test
void testGetPremiumPrice_bloomFilterFalsePositive() {
// Remove one of the premium list entries from behind the Bloom filter's back.
tm().transactNew(
() ->
auditedOfy()
.delete()
.keys(Key.create(pl.getRevisionKey(), PremiumListEntry.class, "rich")));
auditedOfy().clearSessionCache();
assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "rich", "tld")).isEmpty();
assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "rich", "tld")).isEmpty();
assertThat(premiumListChecks)
.hasValueForLabels(1, "tld", "tld", UNCACHED_NEGATIVE.toString())
.and()
.hasValueForLabels(1, "tld", "tld", CACHED_NEGATIVE.toString())
.and()
.hasNoOtherValues();
assertThat(premiumListProcessingTime)
.hasAnyValueForLabels("tld", "tld", UNCACHED_NEGATIVE.toString())
.and()
.hasAnyValueForLabels("tld", "tld", CACHED_NEGATIVE.toString())
.and()
.hasNoOtherValues();
}
@Test
void testSave_removedPremiumListEntries_areNoLongerInDatastore() {
PremiumList pl = persistPremiumList("tld", "genius,USD 10", "dolt,JPY 1000");
assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "genius", "tld"))
.hasValue(Money.parse("USD 10"));
assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "dolt", "tld"))
.hasValue(Money.parse("JPY 1000"));
assertThat(
auditedOfy()
.load()
.type(PremiumListEntry.class)
.parent(pl.getRevisionKey())
.id("dolt")
.now()
.price)
.isEqualTo(Money.parse("JPY 1000"));
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())
.and()
.hasValueForLabels(1, "tld", "tld", BLOOM_FILTER_NEGATIVE.toString())
.and()
.hasNoOtherValues();
assertThat(premiumListProcessingTime)
.hasAnyValueForLabels("tld", "tld", UNCACHED_POSITIVE.toString())
.and()
.hasAnyValueForLabels("tld", "tld", BLOOM_FILTER_NEGATIVE.toString())
.and()
.hasNoOtherValues();
}
@Test
void testGetPremiumPrice_allLabelsAreNonPremium_whenNotInList() {
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 =
PremiumListDatastoreDao.save("tld2", ImmutableList.of("lol , USD 999 # yupper rooni "));
persistResource(Registry.get("tld").asBuilder().setPremiumList(pl).build());
assertThat(PremiumListDatastoreDao.getPremiumPrice("tld2", "lol", "tld"))
.hasValue(Money.parse("USD 999"));
assertThat(PremiumListDatastoreDao.getPremiumPrice("tld2", "lol ", "tld")).isEmpty();
ImmutableMap<String, PremiumListEntry> entries =
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");
assertThat(entry.comment).isEqualTo("yupper rooni");
assertThat(entry.price).isEqualTo(Money.parse("USD 999"));
assertThat(entry.label).isEqualTo("lol");
assertThat(premiumListChecks)
.hasValueForLabels(1, "tld", "tld2", UNCACHED_POSITIVE.toString())
.and()
.hasValueForLabels(1, "tld", "tld2", BLOOM_FILTER_NEGATIVE.toString())
.and()
.hasNoOtherValues();
assertThat(premiumListProcessingTime)
.hasAnyValueForLabels("tld", "tld2", UNCACHED_POSITIVE.toString())
.and()
.hasAnyValueForLabels("tld", "tld2", BLOOM_FILTER_NEGATIVE.toString())
.and()
.hasNoOtherValues();
}
@Test
void test_saveAndUpdateEntriesTwice() {
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");
// Save again with no changes, and clear the cache to force a re-load from Datastore.
PremiumList resaved = PremiumListDatastoreDao.save("tld", ImmutableList.of("test,USD 1"));
auditedOfy().clearSessionCache();
Map<String, PremiumListEntry> entriesReloaded =
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 testDelete() {
persistPremiumList("gtld1", "trombone,USD 10");
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(auditedOfy().load().type(PremiumListEntry.class).ancestor(parent).list()).isEmpty();
}
@Test
void testDelete_largeNumberOfEntries_succeeds() {
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. */
private PremiumList persistHumongousPremiumList(String name, int size) {
String[] entries = new String[size];
for (int i = 0; i < size; i++) {
entries[i] = String.format("%d,USD 100 # blahz", i);
}
return persistPremiumList(name, entries);
}
}
@@ -1,111 +0,0 @@
// 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.EntityTestCase;
import google.registry.model.pricing.StaticPremiumListPricingEngine;
import google.registry.model.registry.Registry;
import google.registry.testing.TestCacheExtension;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link PremiumListDualDao}. */
public class PremiumListDualDaoTest extends EntityTestCase {
// 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");
fakeClock.setAutoIncrementByOneMilli();
}
@AfterEach
void after() {
fakeClock.disableAutoIncrement();
}
@Test
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).");
}
@Test
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]).");
}
@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();
Truth8.assertThat(PremiumListDualDao.getPremiumPrice("blah", Registry.get("ghost"))).isEmpty();
}
@Test
void testGetPremiumPrice_emptyWhenPremiumListDeleted() {
PremiumList toDelete = PremiumListDualDao.getLatestRevision("tld").get();
PremiumListDualDao.delete(toDelete);
Truth8.assertThat(PremiumListDualDao.getPremiumPrice("blah", Registry.get("tld"))).isEmpty();
}
@Test
void getPremiumPrice_returnsNoneWhenNoPremiumListConfigured() {
persistResource(newRegistry("foobar", "FOOBAR").asBuilder().setPremiumList(null).build());
Truth8.assertThat(PremiumListDualDao.getPremiumPrice("rich", Registry.get("foobar"))).isEmpty();
}
}
@@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.hash.BloomFilter;
import google.registry.model.registry.Registry;
import google.registry.model.registry.label.PremiumList.PremiumListEntry;
import google.registry.schema.tld.PremiumListDao;
import google.registry.testing.AppEngineExtension;
import org.joda.money.Money;
import org.junit.jupiter.api.BeforeEach;
@@ -68,7 +69,7 @@ public class PremiumListTest {
@Test
void testBloomFilter() {
PremiumList pl = PremiumListDualDao.getLatestRevision("tld").get();
PremiumList pl = PremiumListDao.getLatestRevision("tld").get();
BloomFilter<String> bloomFilter = pl.getBloomFilter();
assertThat(bloomFilter.mightContain("notpremium")).isFalse();
for (String label : ImmutableList.of("rich", "lol", "johnny-be-goode", "icann")) {
@@ -84,7 +85,7 @@ public class PremiumListTest {
assertThrows(
IllegalStateException.class,
() ->
PremiumListDualDao.getLatestRevision("tld")
PremiumListDao.getLatestRevision("tld")
.get()
.parse(
ImmutableList.of(
@@ -42,7 +42,7 @@ import google.registry.schema.integration.SqlIntegrationTestSuite.AfterSuiteTest
import google.registry.schema.integration.SqlIntegrationTestSuite.BeforeSuiteTest;
import google.registry.schema.registrar.RegistrarDaoTest;
import google.registry.schema.replay.SqlReplayCheckpointTest;
import google.registry.schema.tld.PremiumListSqlDaoTest;
import google.registry.schema.tld.PremiumListDaoTest;
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,
LockTest.class,
PollMessageTest.class,
PremiumListSqlDaoTest.class,
PremiumListDaoTest.class,
RdeRevisionTest.class,
RegistrarDaoTest.class,
RegistryTest.class,
@@ -40,8 +40,8 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link PremiumListSqlDao}. */
public class PremiumListSqlDaoTest {
/** Unit tests for {@link PremiumListDao}. */
public class PremiumListDaoTest {
private final FakeClock fakeClock = new FakeClock();
@@ -58,7 +58,6 @@ public class PremiumListSqlDaoTest {
public final TestCacheExtension testCacheExtension =
new TestCacheExtension.Builder()
.withPremiumListsCache(standardDays(1))
.withPremiumListEntriesCache(standardDays(1))
.build();
private ImmutableMap<String, BigDecimal> testPrices;
@@ -86,12 +85,11 @@ public class PremiumListSqlDaoTest {
@Test
void saveNew_worksSuccessfully() {
PremiumListSqlDao.save(testList);
PremiumListDao.save(testList);
jpaTm()
.transact(
() -> {
Optional<PremiumList> persistedListOpt =
PremiumListSqlDao.getLatestRevision("testname");
Optional<PremiumList> persistedListOpt = PremiumListDao.getLatestRevision("testname");
assertThat(persistedListOpt).isPresent();
PremiumList persistedList = persistedListOpt.get();
assertThat(persistedList.getLabelsToPrices()).containsExactlyEntriesIn(testPrices);
@@ -101,11 +99,11 @@ public class PremiumListSqlDaoTest {
@Test
void update_worksSuccessfully() {
PremiumListSqlDao.save(testList);
Optional<PremiumList> persistedList = PremiumListSqlDao.getLatestRevision("testname");
PremiumListDao.save(testList);
Optional<PremiumList> persistedList = PremiumListDao.getLatestRevision("testname");
assertThat(persistedList).isPresent();
long firstRevisionId = persistedList.get().getRevisionId();
PremiumListSqlDao.save(
PremiumListDao.save(
new PremiumList.Builder()
.setName("testname")
.setCurrency(USD)
@@ -122,7 +120,7 @@ public class PremiumListSqlDaoTest {
jpaTm()
.transact(
() -> {
Optional<PremiumList> savedListOpt = PremiumListSqlDao.getLatestRevision("testname");
Optional<PremiumList> savedListOpt = PremiumListDao.getLatestRevision("testname");
assertThat(savedListOpt).isPresent();
PremiumList savedList = savedListOpt.get();
assertThat(savedList.getLabelsToPrices())
@@ -142,26 +140,26 @@ public class PremiumListSqlDaoTest {
@Test
void checkExists_worksSuccessfully() {
assertThat(PremiumListSqlDao.getLatestRevision("testname")).isEmpty();
PremiumListSqlDao.save(testList);
assertThat(PremiumListSqlDao.getLatestRevision("testname")).isPresent();
assertThat(PremiumListDao.getLatestRevision("testname")).isEmpty();
PremiumListDao.save(testList);
assertThat(PremiumListDao.getLatestRevision("testname")).isPresent();
}
@Test
void getLatestRevision_returnsEmptyForNonexistentList() {
assertThat(PremiumListSqlDao.getLatestRevision("nonexistentlist")).isEmpty();
assertThat(PremiumListDao.getLatestRevision("nonexistentlist")).isEmpty();
}
@Test
void getLatestRevision_worksSuccessfully() {
PremiumListSqlDao.save(
PremiumListDao.save(
new PremiumList.Builder()
.setName("list1")
.setCurrency(JPY)
.setLabelsToPrices(ImmutableMap.of("wrong", BigDecimal.valueOf(1000.50)))
.setCreationTime(fakeClock.nowUtc())
.build());
PremiumListSqlDao.save(
PremiumListDao.save(
new PremiumList.Builder()
.setName("list1")
.setCurrency(JPY)
@@ -171,7 +169,7 @@ public class PremiumListSqlDaoTest {
jpaTm()
.transact(
() -> {
Optional<PremiumList> persistedList = PremiumListSqlDao.getLatestRevision("list1");
Optional<PremiumList> persistedList = PremiumListDao.getLatestRevision("list1");
assertThat(persistedList).isPresent();
assertThat(persistedList.get().getName()).isEqualTo("list1");
assertThat(persistedList.get().getCurrency()).isEqualTo(JPY);
@@ -191,18 +189,16 @@ public class PremiumListSqlDaoTest {
google.registry.model.registry.label.PremiumList.class,
"premlist"))
.build());
PremiumListSqlDao.save(
PremiumListDao.save(
new PremiumList.Builder()
.setName("premlist")
.setCurrency(USD)
.setLabelsToPrices(testPrices)
.setCreationTime(fakeClock.nowUtc())
.build());
assertThat(PremiumListSqlDao.getPremiumPrice("premlist", "silver"))
.hasValue(Money.of(USD, 10.23));
assertThat(PremiumListSqlDao.getPremiumPrice("premlist", "gold"))
.hasValue(Money.of(USD, 1305.47));
assertThat(PremiumListSqlDao.getPremiumPrice("premlist", "zirconium")).isEmpty();
assertThat(PremiumListDao.getPremiumPrice("premlist", "silver")).hasValue(Money.of(USD, 10.23));
assertThat(PremiumListDao.getPremiumPrice("premlist", "gold")).hasValue(Money.of(USD, 1305.47));
assertThat(PremiumListDao.getPremiumPrice("premlist", "zirconium")).isEmpty();
}
@Test
@@ -216,7 +212,7 @@ public class PremiumListSqlDaoTest {
google.registry.model.registry.label.PremiumList.class,
"premlist"))
.build());
PremiumListSqlDao.save(
PremiumListDao.save(
new PremiumList.Builder()
.setName("premlist")
.setCurrency(JPY)
@@ -230,20 +226,20 @@ public class PremiumListSqlDaoTest {
BigDecimal.valueOf(15000)))
.setCreationTime(fakeClock.nowUtc())
.build());
assertThat(PremiumListSqlDao.getPremiumPrice("premlist", "silver")).hasValue(moneyOf(JPY, 10));
assertThat(PremiumListSqlDao.getPremiumPrice("premlist", "gold")).hasValue(moneyOf(JPY, 1000));
assertThat(PremiumListSqlDao.getPremiumPrice("premlist", "palladium"))
assertThat(PremiumListDao.getPremiumPrice("premlist", "silver")).hasValue(moneyOf(JPY, 10));
assertThat(PremiumListDao.getPremiumPrice("premlist", "gold")).hasValue(moneyOf(JPY, 1000));
assertThat(PremiumListDao.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();
assertThat(PremiumListDao.premiumListCache.getIfPresent("testname")).isNull();
PremiumListDao.save(testList);
PremiumList pl = PremiumListDao.getLatestRevision("testname").get();
assertThat(PremiumListDao.premiumListCache.getIfPresent("testname").get()).isEqualTo(pl);
transactIfJpaTm(() -> PremiumListDao.save("testname", ImmutableList.of("test,USD 1")));
assertThat(PremiumListDao.premiumListCache.getIfPresent("testname")).isNull();
}
private static Money moneyOf(CurrencyUnit unit, double amount) {
@@ -30,11 +30,10 @@ import static google.registry.model.EppResourceUtils.createRepoId;
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
import static google.registry.model.ImmutableObjectSubject.immutableObjectCorrespondence;
import static google.registry.model.ResourceTransferUtils.createTransferResponse;
import static google.registry.model.ofy.ObjectifyService.allocateId;
import static google.registry.model.ofy.ObjectifyService.auditedOfy;
import static google.registry.model.registry.Registry.TldState.GENERAL_AVAILABILITY;
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;
@@ -99,8 +98,6 @@ import google.registry.model.registry.Registry.TldState;
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.registry.label.ReservedListDualDatabaseDao;
import google.registry.model.reporting.HistoryEntry;
@@ -110,6 +107,7 @@ import google.registry.model.transfer.DomainTransferData;
import google.registry.model.transfer.TransferData;
import google.registry.model.transfer.TransferStatus;
import google.registry.persistence.VKey;
import google.registry.schema.tld.PremiumListDao;
import google.registry.tmch.LordnTaskUtils;
import java.lang.reflect.Field;
import java.util.List;
@@ -391,33 +389,14 @@ public class DatabaseHelper {
toImmutableMap(
Map.Entry::getKey, entry -> entry.getValue().getValue().getAmount())))
.build();
PremiumListRevision revision = PremiumListRevision.create(premiumList, entries.keySet());
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 {
ofyTm().putAllWithoutBackup(premiumListOfyObjects);
ofyTm().putAllWithoutBackup(entriesOnRevision);
}
// Since we used to persist a PremiumList to Datastore here, it is necessary to allocate an ID
// here to prevent breaking some of the hard-coded flow tests. IDs in tests are allocated in a
// strictly increasing sequence, if we don't pad out the ID here, we would have to renumber
// hundreds of unit tests.
allocateId();
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
// breaks the assumption we have in our application code, see
// PremiumListUtils.savePremiumListAndEntries(). Clearing the session cache can help make sure
// we always get the same list.
tm().clearSessionCache();
return transactIfJpaTm(() -> tm().loadByEntity(premiumList));
return premiumList;
}
/** Creates and persists a tld. */
@@ -1243,7 +1222,7 @@ public class DatabaseHelper {
/** Returns the entire map of {@link PremiumListEntry}s for the given {@link PremiumList}. */
public static ImmutableMap<String, PremiumListEntry> loadPremiumListEntries(
PremiumList premiumList) {
return Streams.stream(PremiumListDualDao.loadAllPremiumListEntries(premiumList.getName()))
return Streams.stream(PremiumListDao.loadAllPremiumListEntries(premiumList.getName()))
.collect(toImmutableMap(PremiumListEntry::getLabel, Function.identity()));
}
@@ -18,8 +18,7 @@ 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.PremiumListDatastoreDao;
import google.registry.schema.tld.PremiumListSqlDao;
import google.registry.schema.tld.PremiumListDao;
import java.util.Map;
import java.util.Optional;
import org.joda.time.Duration;
@@ -72,17 +71,7 @@ public class TestCacheExtension implements BeforeEachCallback, AfterEachCallback
public Builder withPremiumListsCache(Duration expiry) {
cacheHandlerMap.put(
"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(PremiumListDatastoreDao::setPremiumListEntriesCacheForTest, expiry));
new TestCacheHandler(PremiumListDao::setPremiumListCacheForTest, expiry));
return this;
}
@@ -1,86 +0,0 @@
// 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.tools;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.persistence.transaction.TransactionManagerFactory.ofyTm;
import static google.registry.testing.DatabaseHelper.persistPremiumList;
import static org.joda.money.CurrencyUnit.USD;
import com.google.common.collect.ImmutableMap;
import google.registry.model.registry.label.PremiumList;
import google.registry.model.registry.label.PremiumListDatastoreDao;
import google.registry.schema.tld.PremiumListSqlDao;
import java.math.BigDecimal;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class ComparePremiumListsCommandTest extends CommandTestCase<ComparePremiumListsCommand> {
@BeforeEach
void beforeEach() {
persistPremiumList("xn--q9jyb4c", "rich,USD 100");
persistPremiumList("how", "richer,JPY 10000");
}
@Test
void test_success() throws Exception {
runCommand();
assertThat(getStdoutAsString()).isEqualTo("Found 0 unequal list(s).\n");
}
@Test
void test_listMissingFromCloudSql() throws Exception {
jpaTm()
.transact(
() -> {
PremiumList premiumList = PremiumListSqlDao.getLatestRevision("how").get();
PremiumListSqlDao.delete(premiumList);
});
runCommand();
assertThat(getStdoutAsString())
.isEqualTo(
"PremiumList 'how' is present in Datastore, but not in Cloud SQL.\n"
+ "Found 1 unequal list(s).\n");
}
@Test
void test_listMissingFromDatastore() throws Exception {
PremiumList premiumList = PremiumListDatastoreDao.getLatestRevision("how").get();
ofyTm().transact(() -> ofyTm().delete(premiumList));
runCommand();
assertThat(getStdoutAsString())
.isEqualTo(
"PremiumList 'how' is present in Cloud SQL, but not in Datastore.\n"
+ "Found 1 unequal list(s).\n");
}
@Test
void test_listsDiffer() throws Exception {
PremiumListSqlDao.save(
new PremiumList.Builder()
.setName("how")
.setCurrency(USD)
.setLabelsToPrices(ImmutableMap.of("silver", BigDecimal.valueOf(30.03)))
.setCreationTime(fakeClock.nowUtc())
.build());
runCommand();
assertThat(getStdoutAsString())
.isEqualTo(
"PremiumList 'how' has different entries in each database.\n"
+ "Found 1 unequal list(s).\n");
}
}
@@ -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.PremiumListDualDao;
import google.registry.schema.tld.PremiumListDao;
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(PremiumListDualDao.getLatestRevision("baar").get())
.setPremiumList(PremiumListDao.getLatestRevision("baar").get())
.build());
runCommandForced(
"--client=NewRegistrar",
@@ -20,7 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
import com.google.common.io.Files;
import google.registry.model.registry.Registry;
import google.registry.schema.tld.PremiumListSqlDao;
import google.registry.schema.tld.PremiumListDao;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.junit.jupiter.api.BeforeEach;
@@ -40,14 +40,14 @@ class CreatePremiumListCommandTest<C extends CreatePremiumListCommand>
void verify_registryIsSetUpCorrectly() {
// ensure that no premium list is created before running the command
// this check also implicitly verifies the TLD is successfully created;
assertThat(PremiumListSqlDao.getLatestRevision(TLD_TEST).isPresent()).isFalse();
assertThat(PremiumListDao.getLatestRevision(TLD_TEST).isPresent()).isFalse();
}
@Test
void commandRun_successCreateList() throws Exception {
runCommandForced("--name=" + TLD_TEST, "--input=" + premiumTermsPath);
assertThat(registry.getTld().toString()).isEqualTo(TLD_TEST);
assertThat(PremiumListSqlDao.getLatestRevision(TLD_TEST).isPresent()).isTrue();
assertThat(PremiumListDao.getLatestRevision(TLD_TEST).isPresent()).isTrue();
}
@Test
@@ -24,7 +24,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.PremiumListDualDao;
import google.registry.schema.tld.PremiumListDao;
import org.junit.jupiter.api.Test;
/** Unit tests for {@link DeletePremiumListCommand}. */
@@ -35,7 +35,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(PremiumListDualDao.getLatestRevision("xn--q9jyb4c")).isEmpty();
assertThat(PremiumListDao.getLatestRevision("xn--q9jyb4c")).isEmpty();
}
@Test
@@ -56,7 +56,7 @@ class DeletePremiumListCommandTest extends CommandTestCase<DeletePremiumListComm
assertThrows(
IllegalArgumentException.class,
() -> runCommandForced("--name=" + premiumList.getName()));
assertThat(PremiumListDualDao.getLatestRevision(premiumList.getName())).isPresent();
assertThat(PremiumListDao.getLatestRevision(premiumList.getName())).isPresent();
assertThat(thrown)
.hasMessageThat()
.isEqualTo("Cannot delete premium list because it is used on these tld(s): xn--q9jyb4c");
@@ -21,7 +21,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.Files;
import google.registry.model.registry.Registry;
import google.registry.schema.tld.PremiumListSqlDao;
import google.registry.schema.tld.PremiumListDao;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -41,7 +41,7 @@ class UpdatePremiumListCommandTest<C extends UpdatePremiumListCommand>
@Test
void verify_registryIsSetUpCorrectly() {
// ensure that no premium list is created before running the command
assertThat(PremiumListSqlDao.getLatestRevision(TLD_TEST).isPresent()).isTrue();
assertThat(PremiumListDao.getLatestRevision(TLD_TEST).isPresent()).isTrue();
// ensure that there's value in existing premium list;
UpdatePremiumListCommand command = new UpdatePremiumListCommand();
ImmutableSet<String> entries = command.getExistingPremiumListEntry(TLD_TEST);
@@ -20,9 +20,8 @@ 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.schema.tld.PremiumListDao;
import google.registry.testing.AppEngineExtension;
import google.registry.testing.FakeJsonResponse;
import org.joda.money.Money;
@@ -45,7 +44,7 @@ public class CreatePremiumListActionTest {
@BeforeEach
void beforeEach() {
createTlds("foo", "xn--q9jyb4c", "how");
PremiumListDualDao.delete(PremiumListDualDao.getLatestRevision("foo").get());
PremiumListDao.delete(PremiumListDao.getLatestRevision("foo").get());
action = new CreatePremiumListAction();
response = new FakeJsonResponse();
action.response = response;
@@ -89,7 +88,7 @@ public class CreatePremiumListActionTest {
action.override = true;
action.run();
assertThat(response.getStatus()).isEqualTo(SC_OK);
assertThat(loadPremiumListEntries(PremiumListDualDao.getLatestRevision("zanzibar").get()))
assertThat(loadPremiumListEntries(PremiumListDao.getLatestRevision("zanzibar").get()))
.hasSize(1);
}
@@ -99,10 +98,10 @@ public class CreatePremiumListActionTest {
action.inputData = "rich,USD 25\nricher,USD 1000\n";
action.run();
assertThat(response.getStatus()).isEqualTo(SC_OK);
PremiumList premiumList = PremiumListDualDao.getLatestRevision("foo").get();
PremiumList premiumList = PremiumListDao.getLatestRevision("foo").get();
assertThat(loadPremiumListEntries(premiumList)).hasSize(2);
assertThat(PremiumListDualDao.getPremiumPrice("rich", Registry.get("foo")))
assertThat(PremiumListDao.getPremiumPrice(premiumList.getName(), "rich"))
.hasValue(Money.parse("USD 25"));
assertThat(PremiumListDualDao.getPremiumPrice("diamond", Registry.get("foo"))).isEmpty();
assertThat(PremiumListDao.getPremiumPrice(premiumList.getName(), "diamond")).isEmpty();
}
}
@@ -23,10 +23,8 @@ 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.model.registry.label.PremiumListDualDao;
import google.registry.schema.tld.PremiumListSqlDao;
import google.registry.schema.tld.PremiumListDao;
import google.registry.testing.AppEngineExtension;
import google.registry.testing.DatabaseHelper;
import google.registry.testing.FakeJsonResponse;
@@ -81,26 +79,24 @@ class UpdatePremiumListActionTest {
.omitEmptyStrings()
.splitToList(
readResourceUtf8(DatabaseHelper.class, "default_premium_list_testdata.csv"));
PremiumListDualDao.save("foo", inputLines);
PremiumListDao.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(PremiumListDualDao.getLatestRevision("foo").get()))
.hasSize(3);
Truth8.assertThat(PremiumListDualDao.getPremiumPrice("rich", registry))
assertThat(loadPremiumListEntries(PremiumListDao.getLatestRevision("foo").get())).hasSize(3);
Truth8.assertThat(PremiumListDao.getPremiumPrice("foo", "rich"))
.hasValue(Money.parse("USD 75"));
Truth8.assertThat(PremiumListDualDao.getPremiumPrice("richer", registry))
Truth8.assertThat(PremiumListDao.getPremiumPrice("foo", "richer"))
.hasValue(Money.parse("USD 5000"));
Truth8.assertThat(PremiumListDualDao.getPremiumPrice("poor", registry))
Truth8.assertThat(PremiumListDao.getPremiumPrice("foo", "poor"))
.hasValue(Money.parse("USD 0.99"));
Truth8.assertThat(PremiumListDualDao.getPremiumPrice("diamond", registry)).isEmpty();
Truth8.assertThat(PremiumListDao.getPremiumPrice("foo", "diamond")).isEmpty();
jpaTm()
.transact(
() -> {
PremiumList persistedList = PremiumListSqlDao.getLatestRevision("foo").get();
PremiumList persistedList = PremiumListDao.getLatestRevision("foo").get();
assertThat(persistedList.getLabelsToPrices())
.containsEntry("rich", new BigDecimal("75.00"));
assertThat(persistedList.getLabelsToPrices())