Support premium list updating in Cloud SQL (#422)

* Support premium list updating in Cloud SQL

This also removes the requirement to specify --also_cloud_sql in nomulus premium
list tooling, instead always persisting to Cloud SQL. It removes a non-USD
premium label in the global test premium list (the Cloud SQL schema doesn't
support a mix of currency units in a single premium list). And it adds a method
to PremiumListDao to grab the most recent version of a given list.

* Merge branch 'master' into premium-lists-always-cloud-sql

* Revert test change

* Create new PremiumListUtils class and refactor out existing method

* Fix tests and update an existing premium price
This commit is contained in:
Ben McIlwain 2020-01-02 11:30:58 -05:00 committed by GitHub
parent c17a5c489c
commit 8f67c4b9cf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 199 additions and 165 deletions

View file

@ -18,10 +18,13 @@ import google.registry.model.registry.RegistryLockDaoTest;
import google.registry.model.transaction.JpaTestRules.JpaIntegrationTestRule;
import google.registry.schema.cursor.CursorDaoTest;
import google.registry.schema.tld.PremiumListDaoTest;
import google.registry.schema.tld.PremiumListUtilsTest;
import google.registry.schema.tld.ReservedListDaoTest;
import google.registry.schema.tmch.ClaimsListDaoTest;
import google.registry.tools.CreateReservedListCommandTest;
import google.registry.tools.UpdateReservedListCommandTest;
import google.registry.tools.server.CreatePremiumListActionTest;
import google.registry.tools.server.UpdatePremiumListActionTest;
import google.registry.ui.server.registrar.RegistryLockGetActionTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@ -41,10 +44,13 @@ import org.junit.runners.Suite.SuiteClasses;
ClaimsListDaoTest.class,
CreateReservedListCommandTest.class,
CursorDaoTest.class,
CreatePremiumListActionTest.class,
PremiumListDaoTest.class,
PremiumListUtilsTest.class,
RegistryLockDaoTest.class,
RegistryLockGetActionTest.class,
ReservedListDaoTest.class,
UpdatePremiumListActionTest.class,
UpdateReservedListCommandTest.class
})
public class SqlIntegrationTestSuite {}

View file

@ -32,8 +32,8 @@ import google.registry.model.transaction.JpaTestRules;
import google.registry.model.transaction.JpaTestRules.JpaIntegrationTestRule;
import google.registry.testing.AppEngineRule;
import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;
import org.joda.money.CurrencyUnit;
import org.joda.money.Money;
import org.junit.Rule;
import org.junit.Test;
@ -66,13 +66,9 @@ public class PremiumListDaoTest {
jpaTm()
.transact(
() -> {
PremiumList persistedList =
jpaTm()
.getEntityManager()
.createQuery(
"SELECT pl FROM PremiumList pl WHERE pl.name = :name", PremiumList.class)
.setParameter("name", "testname")
.getSingleResult();
Optional<PremiumList> persistedListOpt = PremiumListDao.getLatestRevision("testname");
assertThat(persistedListOpt).isPresent();
PremiumList persistedList = persistedListOpt.get();
assertThat(persistedList.getLabelsToPrices()).containsExactlyEntriesIn(TEST_PRICES);
assertThat(persistedList.getCreationTimestamp())
.isEqualTo(jpaRule.getTxnClock().nowUtc());
@ -81,26 +77,40 @@ public class PremiumListDaoTest {
@Test
public void update_worksSuccessfully() {
PremiumListDao.saveNew(
PremiumListDao.saveNew(PremiumList.create("testname", CurrencyUnit.USD, TEST_PRICES));
Optional<PremiumList> persistedList = PremiumListDao.getLatestRevision("testname");
assertThat(persistedList).isPresent();
long firstRevisionId = persistedList.get().getRevisionId();
PremiumListDao.update(
PremiumList.create(
"testname", USD, ImmutableMap.of("firstversion", BigDecimal.valueOf(123.45))));
PremiumListDao.update(PremiumList.create("testname", USD, TEST_PRICES));
"testname",
CurrencyUnit.USD,
ImmutableMap.of(
"update",
BigDecimal.valueOf(55343.12),
"new",
BigDecimal.valueOf(0.01),
"silver",
BigDecimal.valueOf(30.03))));
jpaTm()
.transact(
() -> {
List<PremiumList> persistedLists =
jpaTm()
.getEntityManager()
.createQuery(
"SELECT pl FROM PremiumList pl WHERE pl.name = :name ORDER BY"
+ " pl.revisionId",
PremiumList.class)
.setParameter("name", "testname")
.getResultList();
assertThat(persistedLists).hasSize(2);
assertThat(persistedLists.get(1).getLabelsToPrices())
.containsExactlyEntriesIn(TEST_PRICES);
assertThat(persistedLists.get(1).getCreationTimestamp())
Optional<PremiumList> updatedListOpt = PremiumListDao.getLatestRevision("testname");
assertThat(updatedListOpt).isPresent();
PremiumList updatedList = updatedListOpt.get();
assertThat(updatedList.getLabelsToPrices())
.containsExactlyEntriesIn(
ImmutableMap.of(
"update",
BigDecimal.valueOf(55343.12),
"new",
BigDecimal.valueOf(0.01),
"silver",
BigDecimal.valueOf(30.03)));
assertThat(updatedList.getCreationTimestamp())
.isEqualTo(jpaRule.getTxnClock().nowUtc());
assertThat(updatedList.getRevisionId()).isGreaterThan(firstRevisionId);
assertThat(updatedList.getCreationTimestamp())
.isEqualTo(jpaRule.getTxnClock().nowUtc());
});
}
@ -116,7 +126,7 @@ public class PremiumListDaoTest {
}
@Test
public void update_throwsWhenPremiumListDoesntExist() {
public void update_throwsWhenListDoesntExist() {
IllegalArgumentException thrown =
assertThrows(
IllegalArgumentException.class,

View file

@ -1,4 +1,4 @@
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
// Copyright 2019 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.
@ -12,43 +12,35 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.tools.server;
package google.registry.schema.tld;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
import static google.registry.schema.tld.PremiumListUtils.parseToPremiumList;
import static google.registry.testing.JUnitBackports.assertThrows;
import google.registry.schema.tld.PremiumList;
import google.registry.model.transaction.JpaTestRules;
import google.registry.model.transaction.JpaTestRules.JpaIntegrationTestRule;
import google.registry.testing.AppEngineRule;
import google.registry.testing.FakeJsonResponse;
import java.math.BigDecimal;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Unit tests for {@link CreateOrUpdatePremiumListAction}. */
/** Unit tests for {@link PremiumListUtils}. */
@RunWith(JUnit4.class)
public class CreateOrUpdatePremiumListActionTest {
public class PremiumListUtilsTest {
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
private CreatePremiumListAction action;
private FakeJsonResponse response;
@Before
public void init() {
action = new CreatePremiumListAction();
response = new FakeJsonResponse();
action.response = response;
action.name = "testlist";
}
@Rule
public final JpaIntegrationTestRule jpaRule =
new JpaTestRules.Builder().buildIntegrationTestRule();
@Test
public void parseInputToPremiumList_works() {
action.inputData = "foo,USD 99.50\n" + "bar,USD 30\n" + "baz,USD 10\n";
PremiumList premiumList = action.parseInputToPremiumList();
PremiumList premiumList =
parseToPremiumList("testlist", "foo,USD 99.50\n" + "bar,USD 30\n" + "baz,USD 10\n");
assertThat(premiumList.getName()).isEqualTo("testlist");
assertThat(premiumList.getLabelsToPrices())
.containsExactly("foo", twoDigits(99.50), "bar", twoDigits(30), "baz", twoDigits(10));
@ -56,9 +48,12 @@ public class CreateOrUpdatePremiumListActionTest {
@Test
public void parseInputToPremiumList_throwsOnInconsistentCurrencies() {
action.inputData = "foo,USD 99.50\n" + "bar,USD 30\n" + "baz,JPY 990\n";
IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, () -> action.parseInputToPremiumList());
assertThrows(
IllegalArgumentException.class,
() ->
parseToPremiumList(
"testlist", "foo,USD 99.50\n" + "bar,USD 30\n" + "baz,JPY 990\n"));
assertThat(thrown)
.hasMessageThat()
.isEqualTo("The Cloud SQL schema requires exactly one currency, but got: [JPY, USD]");

View file

@ -16,9 +16,13 @@ package google.registry.tools;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.DatastoreHelper.persistPremiumList;
import static google.registry.testing.DatastoreHelper.persistResource;
import static google.registry.testing.JUnitBackports.assertThrows;
import com.beust.jcommander.ParameterException;
import google.registry.model.registry.Registry;
import google.registry.model.registry.label.PremiumList;
import google.registry.testing.DeterministicStringGenerator;
import org.junit.Before;
import org.junit.Test;
@ -91,7 +95,14 @@ public class CreateDomainCommandTest extends EppToolCommandTestCase<CreateDomain
}
@Test
public void testSuccess_premiumDomain() throws Exception {
public void testSuccess_premiumJpyDomain() throws Exception {
createTld("baar");
persistPremiumList("baar", "parajiumu,JPY 96083");
persistResource(
Registry.get("baar")
.asBuilder()
.setPremiumList(PremiumList.getUncached("baar").get())
.build());
runCommandForced(
"--client=NewRegistrar",
"--registrant=crr-admin",
@ -99,10 +110,10 @@ public class CreateDomainCommandTest extends EppToolCommandTestCase<CreateDomain
"--techs=crr-tech",
"--period=3",
"--force_premiums",
"parajiumu.tld");
"parajiumu.baar");
eppVerifier.verifySent("domain_create_parajiumu_3yrs.xml");
assertInStdout(
"parajiumu.tld is premium at JPY 96083 per year; "
"parajiumu.baar is premium at JPY 96083 per year; "
+ "sending total cost for 3 year(s) of JPY 288249.");
}

View file

@ -67,13 +67,7 @@ public class CreatePremiumListCommandTest<C extends CreatePremiumListCommand>
verifySentParams(
connection,
servletPath,
ImmutableMap.of(
"name",
"foo",
"inputData",
generateInputData(premiumTermsPath),
"alsoCloudSql",
"false"));
ImmutableMap.of("name", "foo", "inputData", generateInputData(premiumTermsPath)));
}
@Test
@ -84,28 +78,7 @@ public class CreatePremiumListCommandTest<C extends CreatePremiumListCommand>
connection,
servletPath,
ImmutableMap.of(
"name",
"example_premium_terms",
"inputData",
generateInputData(premiumTermsPath),
"alsoCloudSql",
"false"));
}
@Test
public void testRun_alsoCloudSql() throws Exception {
runCommandForced("-i=" + premiumTermsPath, "-n=foo", "--also_cloud_sql");
assertInStdout("Successfully");
verifySentParams(
connection,
servletPath,
ImmutableMap.of(
"name",
"foo",
"inputData",
generateInputData(premiumTermsPath),
"alsoCloudSql",
"true"));
"name", "example_premium_terms", "inputData", generateInputData(premiumTermsPath)));
}
@Test

View file

@ -57,13 +57,7 @@ public class UpdatePremiumListCommandTest<C extends UpdatePremiumListCommand>
verifySentParams(
connection,
servletPath,
ImmutableMap.of(
"name",
"foo",
"inputData",
generateInputData(premiumTermsPath),
"alsoCloudSql",
"false"));
ImmutableMap.of("name", "foo", "inputData", generateInputData(premiumTermsPath)));
}
@Test
@ -74,11 +68,6 @@ public class UpdatePremiumListCommandTest<C extends UpdatePremiumListCommand>
connection,
servletPath,
ImmutableMap.of(
"name",
"example_premium_terms",
"inputData",
generateInputData(premiumTermsPath),
"alsoCloudSql",
"false"));
"name", "example_premium_terms", "inputData", generateInputData(premiumTermsPath)));
}
}

View file

@ -24,6 +24,8 @@ 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.transaction.JpaTestRules;
import google.registry.model.transaction.JpaTestRules.JpaIntegrationTestRule;
import google.registry.testing.AppEngineRule;
import google.registry.testing.FakeJsonResponse;
import org.joda.money.Money;
@ -39,6 +41,10 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class CreatePremiumListActionTest {
@Rule
public final JpaIntegrationTestRule jpaRule =
new JpaTestRules.Builder().buildIntegrationTestRule();
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
CreatePremiumListAction action;
FakeJsonResponse response;

View file

@ -17,14 +17,22 @@ 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.model.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.schema.tld.PremiumListUtils.parseToPremiumList;
import static google.registry.testing.DatastoreHelper.createTlds;
import static google.registry.testing.DatastoreHelper.loadPremiumListEntries;
import static google.registry.util.ResourceUtils.readResourceUtf8;
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.transaction.JpaTestRules;
import google.registry.model.transaction.JpaTestRules.JpaIntegrationTestRule;
import google.registry.schema.tld.PremiumListDao;
import google.registry.testing.AppEngineRule;
import google.registry.testing.DatastoreHelper;
import google.registry.testing.FakeJsonResponse;
import java.math.BigDecimal;
import org.joda.money.Money;
import org.junit.Before;
import org.junit.Rule;
@ -38,10 +46,11 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class UpdatePremiumListActionTest {
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final JpaIntegrationTestRule jpaRule =
new JpaTestRules.Builder().buildIntegrationTestRule();
UpdatePremiumListAction action;
FakeJsonResponse response;
@ -75,6 +84,9 @@ public class UpdatePremiumListActionTest {
@Test
public void test_success() {
PremiumListDao.saveNew(
parseToPremiumList(
"foo", readResourceUtf8(DatastoreHelper.class, "default_premium_list_testdata.csv")));
action.name = "foo";
action.inputData = "rich,USD 75\nricher,USD 5000\npoor, USD 0.99";
action.run();
@ -85,5 +97,19 @@ public class UpdatePremiumListActionTest {
assertThat(getPremiumPrice("richer", registry)).hasValue(Money.parse("USD 5000"));
assertThat(getPremiumPrice("poor", registry)).hasValue(Money.parse("USD 0.99"));
assertThat(getPremiumPrice("diamond", registry)).isEmpty();
jpaTm()
.transact(
() -> {
google.registry.schema.tld.PremiumList persistedList =
PremiumListDao.getLatestRevision("foo").get();
assertThat(persistedList.getLabelsToPrices())
.containsEntry("rich", new BigDecimal("75.00"));
assertThat(persistedList.getLabelsToPrices())
.containsEntry("richer", new BigDecimal("5000.00"));
assertThat(persistedList.getLabelsToPrices())
.containsEntry("poor", BigDecimal.valueOf(0.99));
assertThat(persistedList.getLabelsToPrices()).doesNotContainKey("diamond");
});
}
}

View file

@ -10,4 +10,3 @@ palladium,USD 877
aluminum,USD 11
copper,USD 15
brass,USD 20
parajiumu,JPY 96083

1 rich USD 100
10 aluminum USD 11
11 copper USD 15
12 brass USD 20
parajiumu JPY 96083

View file

@ -4,7 +4,7 @@
<create>
<domain:create
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>parajiumu.tld</domain:name>
<domain:name>parajiumu.baar</domain:name>
<domain:period unit="y">3</domain:period>
<domain:registrant>crr-admin</domain:registrant>
<domain:contact type="admin">crr-admin</domain:contact>