Add some helper methods to JPA test extension (#1673)

Added methods that exist in AppEngineExtension that preload some canned
data. This data is loaded by default and a lot of tests rely on them. As
we migrate away from App Engine, it is helpful to have them in the JPA
test extension which will replace the app engine extension that is
used to set up the database in dual database tests.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/google/nomulus/1673)
<!-- Reviewable:end -->
This commit is contained in:
Lai Jiang 2022-06-21 16:53:56 -04:00 committed by GitHub
parent 181125a99c
commit a334bb5ceb
4 changed files with 158 additions and 19 deletions

View file

@ -67,7 +67,10 @@ public class RegistryJpaReadTest {
@RegisterExtension
final transient JpaIntegrationTestExtension database =
new JpaTestExtensions.Builder().withClock(fakeClock).buildIntegrationTestExtension();
new JpaTestExtensions.Builder()
.withClock(fakeClock)
.withoutCannedData()
.buildIntegrationTestExtension();
@RegisterExtension
final transient TestPipelineExtension testPipeline =

View file

@ -32,7 +32,10 @@ public class ClaimsListDaoTest {
@RegisterExtension
final JpaIntegrationWithCoverageExtension jpa =
new JpaTestExtensions.Builder().withClock(fakeClock).buildIntegrationWithCoverageExtension();
new JpaTestExtensions.Builder()
.withClock(fakeClock)
.withoutCannedData()
.buildIntegrationWithCoverageExtension();
@Test
void save_insertsClaimsListSuccessfully() {

View file

@ -52,8 +52,15 @@ public class JpaTestExtensions {
private JpaIntegrationTestExtension(
Clock clock,
ImmutableList<Class<?>> extraEntityClasses,
ImmutableMap<String, String> userProperties) {
super(clock, Optional.of(GOLDEN_SCHEMA_SQL_PATH), extraEntityClasses, userProperties);
ImmutableMap<String, String> userProperties,
boolean withCannedData) {
super(
clock,
Optional.of(GOLDEN_SCHEMA_SQL_PATH),
true,
extraEntityClasses,
userProperties,
withCannedData);
}
}
@ -67,7 +74,7 @@ public class JpaTestExtensions {
Optional<String> initScriptPath,
ImmutableList<Class<?>> extraEntityClasses,
ImmutableMap<String, String> userProperties) {
super(clock, initScriptPath, false, extraEntityClasses, userProperties);
super(clock, initScriptPath, false, extraEntityClasses, userProperties, false);
}
}
@ -109,6 +116,7 @@ public class JpaTestExtensions {
private Clock clock;
private List<Class<?>> extraEntityClasses = new ArrayList<>();
private Map<String, String> userProperties = new HashMap<>();
private boolean withoutCannedData = false;
/**
* Sets the SQL script to be used to initialize the database. If not set,
@ -132,6 +140,12 @@ public class JpaTestExtensions {
return this;
}
/** Disables insertion of canned data. */
public Builder withoutCannedData() {
this.withoutCannedData = true;
return this;
}
/** Adds the specified property to those used to initialize the transaction manager. */
Builder withProperty(String name, String value) {
this.userProperties.put(name, value);
@ -154,7 +168,8 @@ public class JpaTestExtensions {
return new JpaIntegrationTestExtension(
clock == null ? new FakeClock(DateTime.now(UTC)) : clock,
ImmutableList.copyOf(extraEntityClasses),
ImmutableMap.copyOf(userProperties));
ImmutableMap.copyOf(userProperties),
!withoutCannedData);
}
/**

View file

@ -17,6 +17,7 @@ package google.registry.persistence.transaction;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertWithMessage;
import static google.registry.testing.DatabaseHelper.insertSimpleResources;
import static org.testcontainers.containers.PostgreSQLContainer.POSTGRESQL_PORT;
import com.google.common.base.Charsets;
@ -24,9 +25,14 @@ import com.google.common.base.Joiner;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Streams;
import com.google.common.io.Resources;
import google.registry.model.registrar.Registrar;
import google.registry.model.registrar.Registrar.State;
import google.registry.model.registrar.RegistrarAddress;
import google.registry.model.registrar.RegistrarContact;
import google.registry.persistence.HibernateSchemaExporter;
import google.registry.persistence.NomulusPostgreSql;
import google.registry.persistence.PersistenceModule;
@ -56,6 +62,7 @@ import javax.persistence.EntityManagerFactory;
import org.hibernate.cfg.Environment;
import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor;
import org.hibernate.jpa.boot.spi.Bootstrap;
import org.joda.money.CurrencyUnit;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
@ -83,6 +90,9 @@ abstract class JpaTransactionManagerExtension implements BeforeEachCallback, Aft
// is documented in PSQL's official user guide.
private static final String CONNECTION_BACKEND_TYPE = "client backend";
private static final int ACTIVE_CONNECTIONS_CAP = 5;
public static final String NEW_REGISTRAR_GAE_USER_ID = "666";
public static final String THE_REGISTRAR_GAE_USER_ID = "31337";
public static final String MARLA_SINGER_GAE_USER_ID = "12345";
private final Clock clock;
private final Optional<String> initScriptPath;
@ -107,30 +117,23 @@ abstract class JpaTransactionManagerExtension implements BeforeEachCallback, Aft
// to false.
private boolean includeNomulusSchema = true;
// Whether to prepolulate some registrars for ease of testing.
private boolean withCannedData = false;
JpaTransactionManagerExtension(
Clock clock,
Optional<String> initScriptPath,
boolean includeNomulusSchema,
ImmutableList<Class<?>> extraEntityClasses,
ImmutableMap<String, String> userProperties) {
ImmutableMap<String, String> userProperties,
boolean withCannedData) {
this.clock = clock;
this.initScriptPath = initScriptPath;
this.includeNomulusSchema = includeNomulusSchema;
this.extraEntityClasses = extraEntityClasses;
this.userProperties = userProperties;
this.entityHash = getOrmEntityHash(initScriptPath, extraEntityClasses);
}
JpaTransactionManagerExtension(
Clock clock,
Optional<String> initScriptPath,
ImmutableList<Class<?>> extraEntityClasses,
ImmutableMap<String, String> userProperties) {
this.clock = clock;
this.initScriptPath = initScriptPath;
this.extraEntityClasses = extraEntityClasses;
this.userProperties = userProperties;
this.entityHash = getOrmEntityHash(initScriptPath, extraEntityClasses);
this.withCannedData = withCannedData;
}
private static JdbcDatabaseContainer create() {
@ -218,6 +221,9 @@ abstract class JpaTransactionManagerExtension implements BeforeEachCallback, Aft
TransactionManagerFactory.setJpaTm(Suppliers.ofInstance(txnManager));
TransactionManagerFactory.setReplicaJpaTm(
Suppliers.ofInstance(new ReplicaSimulatingJpaTransactionManager(txnManager)));
if (withCannedData) {
loadInitialData();
}
}
@Override
@ -322,6 +328,118 @@ abstract class JpaTransactionManagerExtension implements BeforeEachCallback, Aft
}
}
private static Registrar.Builder makeRegistrarCommon() {
return new Registrar.Builder()
.setType(Registrar.Type.REAL)
.setState(State.ACTIVE)
.setIcannReferralEmail("lol@sloth.test")
.setUrl("http://my.fake.url")
.setInternationalizedAddress(
new RegistrarAddress.Builder()
.setStreet(ImmutableList.of("123 Example Boulevard"))
.setCity("Williamsburg")
.setState("NY")
.setZip("11211")
.setCountryCode("US")
.build())
.setLocalizedAddress(
new RegistrarAddress.Builder()
.setStreet(ImmutableList.of("123 Example B\u0151ulevard"))
.setCity("Williamsburg")
.setState("NY")
.setZip("11211")
.setCountryCode("US")
.build())
.setPhoneNumber("+1.3334445555")
.setPhonePasscode("12345")
.setBillingAccountMap(ImmutableMap.of(CurrencyUnit.USD, "abc123"))
.setContactsRequireSyncing(true);
}
/** Public factory for first Registrar to allow comparison against stored value in unit tests. */
public static Registrar makeRegistrar1() {
return makeRegistrarCommon()
.setRegistrarId("NewRegistrar")
.setRegistrarName("New Registrar")
.setEmailAddress("new.registrar@example.com")
.setIanaIdentifier(8L)
.setPassword("foo-BAR2")
.setPhoneNumber("+1.3334445555")
.setPhonePasscode("12345")
.setRegistryLockAllowed(false)
.build();
}
/** Public factory for second Registrar to allow comparison against stored value in unit tests. */
public static Registrar makeRegistrar2() {
return makeRegistrarCommon()
.setRegistrarId("TheRegistrar")
.setRegistrarName("The Registrar")
.setEmailAddress("the.registrar@example.com")
.setIanaIdentifier(1L)
.setPassword("password2")
.setPhoneNumber("+1.2223334444")
.setPhonePasscode("22222")
.setRegistryLockAllowed(true)
.build();
}
/**
* Public factory for first RegistrarContact to allow comparison against stored value in unit
* tests.
*/
public static RegistrarContact makeRegistrarContact1() {
return new RegistrarContact.Builder()
.setParent(makeRegistrar1())
.setName("Jane Doe")
.setVisibleInWhoisAsAdmin(true)
.setVisibleInWhoisAsTech(false)
.setEmailAddress("janedoe@theregistrar.com")
.setPhoneNumber("+1.1234567890")
.setTypes(ImmutableSet.of(RegistrarContact.Type.ADMIN))
.build();
}
/**
* Public factory for second RegistrarContact to allow comparison against stored value in unit
* tests.
*/
public static RegistrarContact makeRegistrarContact2() {
return new RegistrarContact.Builder()
.setParent(makeRegistrar2())
.setName("John Doe")
.setEmailAddress("johndoe@theregistrar.com")
.setPhoneNumber("+1.1234567890")
.setTypes(ImmutableSet.of(RegistrarContact.Type.ADMIN))
.setGaeUserId(THE_REGISTRAR_GAE_USER_ID)
.build();
}
public static RegistrarContact makeRegistrarContact3() {
return new RegistrarContact.Builder()
.setParent(makeRegistrar2())
.setName("Marla Singer")
.setEmailAddress("Marla.Singer@crr.com")
.setRegistryLockEmailAddress("Marla.Singer.RegistryLock@crr.com")
.setPhoneNumber("+1.2128675309")
.setTypes(ImmutableSet.of(RegistrarContact.Type.TECH))
.setGaeUserId(MARLA_SINGER_GAE_USER_ID)
.setAllowedToSetRegistryLockPassword(true)
.setRegistryLockPassword("hi")
.build();
}
/** Create some fake registrars. */
public static void loadInitialData() {
insertSimpleResources(
ImmutableList.of(
makeRegistrar1(),
makeRegistrarContact1(),
makeRegistrar2(),
makeRegistrarContact2(),
makeRegistrarContact3()));
}
/** Constructs the {@link EntityManagerFactory} instance. */
private EntityManagerFactory createEntityManagerFactory(ImmutableMap<String, String> properties) {
ParsedPersistenceXmlDescriptor descriptor =