diff --git a/core/src/test/java/google/registry/model/registry/RegistryLockDaoTest.java b/core/src/test/java/google/registry/model/registry/RegistryLockDaoTest.java index c2c6bd4e4..d5e0f9e36 100644 --- a/core/src/test/java/google/registry/model/registry/RegistryLockDaoTest.java +++ b/core/src/test/java/google/registry/model/registry/RegistryLockDaoTest.java @@ -20,9 +20,10 @@ import static google.registry.persistence.transaction.TransactionManagerFactory. import static org.junit.Assert.assertThrows; import google.registry.persistence.transaction.JpaTestRules; -import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationTestRule; +import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule; import google.registry.schema.domain.RegistryLock; import google.registry.testing.AppEngineRule; +import google.registry.testing.FakeClock; import java.util.Optional; import java.util.UUID; import org.junit.Rule; @@ -34,11 +35,13 @@ import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public final class RegistryLockDaoTest { + private final FakeClock fakeClock = new FakeClock(); + @Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build(); @Rule - public final JpaIntegrationTestRule jpaRule = - new JpaTestRules.Builder().buildIntegrationTestRule(); + public final JpaIntegrationWithCoverageRule jpaRule = + new JpaTestRules.Builder().withClock(fakeClock).buildIntegrationWithCoverageRule(); @Test public void testSaveAndLoad_success() { @@ -48,24 +51,21 @@ public final class RegistryLockDaoTest { RegistryLockDao.getByVerificationCode(lock.getVerificationCode()).get(); assertThat(fromDatabase.getDomainName()).isEqualTo(lock.getDomainName()); assertThat(fromDatabase.getVerificationCode()).isEqualTo(lock.getVerificationCode()); - assertThat(fromDatabase.getLastUpdateTimestamp()).isEqualTo(jpaRule.getTxnClock().nowUtc()); + assertThat(fromDatabase.getLastUpdateTimestamp()).isEqualTo(fakeClock.nowUtc()); } @Test public void testSaveTwiceAndLoad_returnsLatest() { RegistryLock lock = createLock(); jpaTm().transact(() -> RegistryLockDao.save(lock)); - jpaRule.getTxnClock().advanceOneMilli(); + fakeClock.advanceOneMilli(); jpaTm() .transact( () -> { RegistryLock updatedLock = RegistryLockDao.getByVerificationCode(lock.getVerificationCode()).get(); RegistryLockDao.save( - updatedLock - .asBuilder() - .setLockCompletionTimestamp(jpaRule.getTxnClock().nowUtc()) - .build()); + updatedLock.asBuilder().setLockCompletionTimestamp(fakeClock.nowUtc()).build()); }); jpaTm() .transact( @@ -73,9 +73,8 @@ public final class RegistryLockDaoTest { RegistryLock fromDatabase = RegistryLockDao.getByVerificationCode(lock.getVerificationCode()).get(); assertThat(fromDatabase.getLockCompletionTimestamp().get()) - .isEqualTo(jpaRule.getTxnClock().nowUtc()); - assertThat(fromDatabase.getLastUpdateTimestamp()) - .isEqualTo(jpaRule.getTxnClock().nowUtc()); + .isEqualTo(fakeClock.nowUtc()); + assertThat(fromDatabase.getLastUpdateTimestamp()).isEqualTo(fakeClock.nowUtc()); }); } @@ -85,26 +84,25 @@ public final class RegistryLockDaoTest { RegistryLockDao.save( createLock() .asBuilder() - .setLockCompletionTimestamp(jpaRule.getTxnClock().nowUtc()) - .setUnlockRequestTimestamp(jpaRule.getTxnClock().nowUtc()) - .setUnlockCompletionTimestamp(jpaRule.getTxnClock().nowUtc()) + .setLockCompletionTimestamp(fakeClock.nowUtc()) + .setUnlockRequestTimestamp(fakeClock.nowUtc()) + .setUnlockCompletionTimestamp(fakeClock.nowUtc()) .build()); RegistryLockDao.save(lock); RegistryLock fromDatabase = RegistryLockDao.getByVerificationCode(lock.getVerificationCode()).get(); - assertThat(fromDatabase.getUnlockRequestTimestamp()) - .isEqualTo(Optional.of(jpaRule.getTxnClock().nowUtc())); + assertThat(fromDatabase.getUnlockRequestTimestamp()).isEqualTo(Optional.of(fakeClock.nowUtc())); assertThat(fromDatabase.getUnlockCompletionTimestamp()) - .isEqualTo(Optional.of(jpaRule.getTxnClock().nowUtc())); + .isEqualTo(Optional.of(fakeClock.nowUtc())); assertThat(fromDatabase.isLocked()).isFalse(); } @Test public void testUpdateLock_usingSamePrimaryKey() { RegistryLock lock = RegistryLockDao.save(createLock()); - jpaRule.getTxnClock().advanceOneMilli(); + fakeClock.advanceOneMilli(); RegistryLock updatedLock = - lock.asBuilder().setLockCompletionTimestamp(jpaRule.getTxnClock().nowUtc()).build(); + lock.asBuilder().setLockCompletionTimestamp(fakeClock.nowUtc()).build(); jpaTm().transact(() -> RegistryLockDao.save(updatedLock)); jpaTm() .transact( @@ -112,7 +110,7 @@ public final class RegistryLockDaoTest { RegistryLock fromDatabase = RegistryLockDao.getByVerificationCode(lock.getVerificationCode()).get(); assertThat(fromDatabase.getLockCompletionTimestamp()) - .isEqualTo(Optional.of(jpaRule.getTxnClock().nowUtc())); + .isEqualTo(Optional.of(fakeClock.nowUtc())); }); } @@ -129,20 +127,20 @@ public final class RegistryLockDaoTest { @Test public void testLoad_lockedDomains_byRegistrarId() { RegistryLock lock = - createLock().asBuilder().setLockCompletionTimestamp(jpaRule.getTxnClock().nowUtc()).build(); + createLock().asBuilder().setLockCompletionTimestamp(fakeClock.nowUtc()).build(); RegistryLock secondLock = createLock() .asBuilder() .setDomainName("otherexample.test") - .setLockCompletionTimestamp(jpaRule.getTxnClock().nowUtc()) + .setLockCompletionTimestamp(fakeClock.nowUtc()) .build(); RegistryLock unlockedLock = createLock() .asBuilder() .setDomainName("unlocked.test") - .setLockCompletionTimestamp(jpaRule.getTxnClock().nowUtc()) - .setUnlockRequestTimestamp(jpaRule.getTxnClock().nowUtc()) - .setUnlockCompletionTimestamp(jpaRule.getTxnClock().nowUtc()) + .setLockCompletionTimestamp(fakeClock.nowUtc()) + .setUnlockRequestTimestamp(fakeClock.nowUtc()) + .setUnlockCompletionTimestamp(fakeClock.nowUtc()) .build(); RegistryLockDao.save(lock); RegistryLockDao.save(secondLock); @@ -159,10 +157,10 @@ public final class RegistryLockDaoTest { @Test public void testLoad_byRepoId() { RegistryLock completedLock = - createLock().asBuilder().setLockCompletionTimestamp(jpaRule.getTxnClock().nowUtc()).build(); + createLock().asBuilder().setLockCompletionTimestamp(fakeClock.nowUtc()).build(); RegistryLockDao.save(completedLock); - jpaRule.getTxnClock().advanceOneMilli(); + fakeClock.advanceOneMilli(); RegistryLock inProgressLock = createLock(); RegistryLockDao.save(inProgressLock); @@ -179,10 +177,10 @@ public final class RegistryLockDaoTest { @Test public void testLoad_verified_byRepoId() { RegistryLock completedLock = - createLock().asBuilder().setLockCompletionTimestamp(jpaRule.getTxnClock().nowUtc()).build(); + createLock().asBuilder().setLockCompletionTimestamp(fakeClock.nowUtc()).build(); RegistryLockDao.save(completedLock); - jpaRule.getTxnClock().advanceOneMilli(); + fakeClock.advanceOneMilli(); RegistryLock inProgressLock = createLock(); RegistryLockDao.save(inProgressLock); diff --git a/core/src/test/java/google/registry/persistence/CreateAutoTimestampConverterTest.java b/core/src/test/java/google/registry/persistence/CreateAutoTimestampConverterTest.java index beb117c37..19da4f2dc 100644 --- a/core/src/test/java/google/registry/persistence/CreateAutoTimestampConverterTest.java +++ b/core/src/test/java/google/registry/persistence/CreateAutoTimestampConverterTest.java @@ -20,6 +20,7 @@ import google.registry.model.CreateAutoTimestamp; import google.registry.model.ImmutableObject; import google.registry.persistence.transaction.JpaTestRules; import google.registry.persistence.transaction.JpaTestRules.JpaUnitTestRule; +import google.registry.testing.FakeClock; import javax.persistence.Entity; import javax.persistence.Id; import org.joda.time.DateTime; @@ -32,9 +33,14 @@ import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public class CreateAutoTimestampConverterTest { + private final FakeClock fakeClock = new FakeClock(); + @Rule public final JpaUnitTestRule jpaRule = - new JpaTestRules.Builder().withEntityClass(TestEntity.class).buildUnitTestRule(); + new JpaTestRules.Builder() + .withClock(fakeClock) + .withEntityClass(TestEntity.class) + .buildUnitTestRule(); @Test public void testTypeConversion() { @@ -56,7 +62,7 @@ public class CreateAutoTimestampConverterTest { TestEntity result = jpaTm().transact(() -> jpaTm().getEntityManager().find(TestEntity.class, "autoinit")); - assertThat(result.cat.getTimestamp()).isEqualTo(jpaRule.getTxnClock().nowUtc()); + assertThat(result.cat.getTimestamp()).isEqualTo(fakeClock.nowUtc()); } @Entity(name = "TestEntity") // Override entity name to avoid the nested class reference. diff --git a/core/src/test/java/google/registry/persistence/UpdateAutoTimestampConverterTest.java b/core/src/test/java/google/registry/persistence/UpdateAutoTimestampConverterTest.java index 8e772523f..a6b1fb544 100644 --- a/core/src/test/java/google/registry/persistence/UpdateAutoTimestampConverterTest.java +++ b/core/src/test/java/google/registry/persistence/UpdateAutoTimestampConverterTest.java @@ -20,6 +20,7 @@ import google.registry.model.ImmutableObject; import google.registry.model.UpdateAutoTimestamp; import google.registry.persistence.transaction.JpaTestRules; import google.registry.persistence.transaction.JpaTestRules.JpaUnitTestRule; +import google.registry.testing.FakeClock; import javax.persistence.Entity; import javax.persistence.Id; import org.junit.Rule; @@ -31,9 +32,14 @@ import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public class UpdateAutoTimestampConverterTest { + private final FakeClock fakeClock = new FakeClock(); + @Rule public final JpaUnitTestRule jpaRule = - new JpaTestRules.Builder().withEntityClass(TestEntity.class).buildUnitTestRule(); + new JpaTestRules.Builder() + .withClock(fakeClock) + .withEntityClass(TestEntity.class) + .buildUnitTestRule(); @Test public void testTypeConversion() { @@ -45,7 +51,7 @@ public class UpdateAutoTimestampConverterTest { jpaTm().transact(() -> jpaTm().getEntityManager().find(TestEntity.class, "myinst")); assertThat(result.name).isEqualTo("myinst"); - assertThat(result.uat.getTimestamp()).isEqualTo(jpaRule.getTxnClock().nowUtc()); + assertThat(result.uat.getTimestamp()).isEqualTo(fakeClock.nowUtc()); } @Test @@ -57,7 +63,7 @@ public class UpdateAutoTimestampConverterTest { TestEntity result1 = jpaTm().transact(() -> jpaTm().getEntityManager().find(TestEntity.class, "myinst1")); - jpaRule.getTxnClock().advanceOneMilli(); + fakeClock.advanceOneMilli(); TestEntity ent2 = new TestEntity("myinst2", result1.uat); @@ -67,7 +73,7 @@ public class UpdateAutoTimestampConverterTest { jpaTm().transact(() -> jpaTm().getEntityManager().find(TestEntity.class, "myinst2")); assertThat(result1.uat.getTimestamp()).isNotEqualTo(result2.uat.getTimestamp()); - assertThat(result2.uat.getTimestamp()).isEqualTo(jpaRule.getTxnClock().nowUtc()); + assertThat(result2.uat.getTimestamp()).isEqualTo(fakeClock.nowUtc()); } @Entity(name = "TestEntity") // Override entity name to avoid the nested class reference. diff --git a/core/src/test/java/google/registry/persistence/transaction/JpaEntityCoverage.java b/core/src/test/java/google/registry/persistence/transaction/JpaEntityCoverage.java new file mode 100644 index 000000000..8030d444a --- /dev/null +++ b/core/src/test/java/google/registry/persistence/transaction/JpaEntityCoverage.java @@ -0,0 +1,115 @@ +// Copyright 2018 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.persistence.transaction; + +import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import google.registry.persistence.PersistenceXmlUtility; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.persistence.Entity; +import org.junit.rules.ExternalResource; + +/** + * Checks for JPA {@link Entity entities} that are declared in persistence.xml but not persisted in + * integration tests. + */ +public class JpaEntityCoverage extends ExternalResource { + + // TODO(weiminyu): remove this set after pr/438 is submitted. The pr is expected to fix the + // problems with these entities and allow them to be tested. + private static final ImmutableSet IGNORE_ENTITIES = + ImmutableSet.of( + "DomainBase", + "BaseTransferObject", + "DelegationSignerData", + "DesignatedContact", + "GracePeriod"); + + private static final ImmutableSet ALL_JPA_ENTITIES = + PersistenceXmlUtility.getManagedClasses().stream() + .filter(e -> !IGNORE_ENTITIES.contains(e.getSimpleName())) + .filter(e -> e.getAnnotation(Entity.class) != null) + .collect(ImmutableSet.toImmutableSet()); + private static final Set allCoveredJpaEntities = Sets.newHashSet(); + // Map of test class name to boolean flag indicating if it tests any JPA entities. + private static final Map testsJpaEntities = Maps.newHashMap(); + + // Provides class name of the test being executed. + private final TestCaseWatcher watcher; + + public JpaEntityCoverage(TestCaseWatcher watcher) { + this.watcher = watcher; + } + + @Override + public void before() { + testsJpaEntities.putIfAbsent(watcher.getTestClass(), false); + } + + @Override + public void after() { + ALL_JPA_ENTITIES.stream() + .filter(JpaEntityCoverage::isPersisted) + .forEach( + entity -> { + allCoveredJpaEntities.add(entity); + testsJpaEntities.put(watcher.getTestClass(), true); + }); + } + + public static void init() { + allCoveredJpaEntities.clear(); + testsJpaEntities.clear(); + } + + public static Set getUncoveredEntities() { + return Sets.difference(ALL_JPA_ENTITIES, allCoveredJpaEntities); + } + + public static ImmutableList getIrrelevantTestClasses() { + return testsJpaEntities.entrySet().stream() + .filter(e -> !e.getValue()) + .map(Map.Entry::getKey) + .collect(ImmutableList.toImmutableList()); + } + + /** + * Checks if at least one instance of {@code entityType} has been persisted during the test, and + * if yes, reads one of them back. If the read is successful, there is no incompatibility between + * server and schema regarding type. + * + * @return true if an instance of {@code entityType} is found in the database and can be read + */ + private static boolean isPersisted(Class entityType) { + List result = + jpaTm() + .transact( + () -> + jpaTm() + .getEntityManager() + .createQuery( + String.format("SELECT e FROM %s e", entityType.getSimpleName()), + entityType) + .setMaxResults(1) + .getResultList()); + return !result.isEmpty() && entityType.isInstance(result.get(0)); + } +} diff --git a/core/src/test/java/google/registry/persistence/transaction/JpaTestRules.java b/core/src/test/java/google/registry/persistence/transaction/JpaTestRules.java index 4b7aa5830..c4ecd1ea1 100644 --- a/core/src/test/java/google/registry/persistence/transaction/JpaTestRules.java +++ b/core/src/test/java/google/registry/persistence/transaction/JpaTestRules.java @@ -15,57 +15,92 @@ package google.registry.persistence.transaction; import static com.google.common.base.Preconditions.checkState; +import static org.joda.time.DateTimeZone.UTC; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import google.registry.testing.FakeClock; +import google.registry.util.Clock; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; +import org.joda.time.DateTime; +import org.junit.rules.RuleChain; +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; /** * Holds specialized JUnit rules that start a test database server and provide {@link * JpaTransactionManager} instances. */ public class JpaTestRules { - private static final String GOLDEN_SCHEMA_SQL_PATH = "sql/schema/nomulus.golden.sql"; /** * Junit rule for integration tests with JPA framework, when the underlying database is populated * with the Nomulus Cloud SQL schema. - * - *

Test classes that instantiate this class should be included in {@link - * google.registry.schema.integration.SqlIntegrationTestSuite}. This enforced by {@link - * google.registry.schema.integration.SqlIntegrationMembershipTest}. */ public static class JpaIntegrationTestRule extends JpaTransactionManagerRule { private JpaIntegrationTestRule( - ImmutableList extraEntityClasses, ImmutableMap userProperties) { - super(Optional.of(GOLDEN_SCHEMA_SQL_PATH), extraEntityClasses, userProperties); + Clock clock, + ImmutableList extraEntityClasses, + ImmutableMap userProperties) { + super(clock, Optional.of(GOLDEN_SCHEMA_SQL_PATH), extraEntityClasses, userProperties); } } /** * Junit rule for unit tests with JPA framework, when the underlying database is populated by the - * optional init script. + * optional init script (which must not be the Nomulus Cloud SQL schema). */ public static class JpaUnitTestRule extends JpaTransactionManagerRule { private JpaUnitTestRule( + Clock clock, Optional initScriptPath, ImmutableList extraEntityClasses, ImmutableMap userProperties) { - super(initScriptPath, extraEntityClasses, userProperties); + super(clock, initScriptPath, extraEntityClasses, userProperties); + } + } + + /** + * Junit rule for member classes of {@link + * google.registry.schema.integration.SqlIntegrationTestSuite}. In addition to providing a + * database through {@link JpaIntegrationTestRule}, it also keeps track of the test coverage of + * the declare JPA entities (in persistence.xml). + * + *

It is enforced through tests that all test classes using this rule must be included in the + * {@code SqlIntegrationTestSuite}. For the sake of efficiency, end-to-end tests that mainly test + * non-database functionalities should not use this rule. + */ + public static final class JpaIntegrationWithCoverageRule implements TestRule { + private final RuleChain ruleChain; + + JpaIntegrationWithCoverageRule(JpaIntegrationTestRule integrationTestRule) { + TestCaseWatcher watcher = new TestCaseWatcher(); + this.ruleChain = + RuleChain.outerRule(watcher) + .around(integrationTestRule) + .around(new JpaEntityCoverage(watcher)); + } + + @Override + public Statement apply(Statement base, Description description) { + return ruleChain.apply(base, description); } } /** Builder of test rules that provide {@link JpaTransactionManager}. */ public static class Builder { private String initScript; + private Clock clock; private List extraEntityClasses = new ArrayList(); private Map userProperties = new HashMap(); @@ -80,6 +115,11 @@ public class JpaTestRules { return this; } + public Builder withClock(Clock clock) { + this.clock = clock; + return this; + } + /** Adds annotated class(es) to the known entities for the database. */ public Builder withEntityClass(Class... classes) { this.extraEntityClasses.addAll(ImmutableSet.copyOf(classes)); @@ -94,14 +134,28 @@ public class JpaTestRules { /** Builds a {@link JpaIntegrationTestRule} instance. */ public JpaIntegrationTestRule buildIntegrationTestRule() { - checkState(initScript == null, "JpaNomulusIntegrationTestRule does not accept initScript"); return new JpaIntegrationTestRule( - ImmutableList.copyOf(extraEntityClasses), ImmutableMap.copyOf(userProperties)); + clock == null ? new FakeClock(DateTime.now(UTC)) : clock, + ImmutableList.copyOf(extraEntityClasses), + ImmutableMap.copyOf(userProperties)); + } + + /** + * Builds a {@link RuleChain} around {@link JpaIntegrationTestRule} that also checks test + * coverage of JPA entity classes. + */ + public JpaIntegrationWithCoverageRule buildIntegrationWithCoverageRule() { + checkState(initScript == null, "Integration tests do not accept initScript"); + return new JpaIntegrationWithCoverageRule(buildIntegrationTestRule()); } /** Builds a {@link JpaUnitTestRule} instance. */ public JpaUnitTestRule buildUnitTestRule() { + checkState( + !Objects.equals(GOLDEN_SCHEMA_SQL_PATH, initScript), + "Unit tests must not depend on the Nomulus schema."); return new JpaUnitTestRule( + clock == null ? new FakeClock(DateTime.now(UTC)) : clock, Optional.ofNullable(initScript), ImmutableList.copyOf(extraEntityClasses), ImmutableMap.copyOf(userProperties)); diff --git a/core/src/test/java/google/registry/persistence/transaction/JpaTransactionManagerImplTest.java b/core/src/test/java/google/registry/persistence/transaction/JpaTransactionManagerImplTest.java index 1107e4580..be2383d81 100644 --- a/core/src/test/java/google/registry/persistence/transaction/JpaTransactionManagerImplTest.java +++ b/core/src/test/java/google/registry/persistence/transaction/JpaTransactionManagerImplTest.java @@ -33,10 +33,13 @@ import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public class JpaTransactionManagerImplTest { + private final FakeClock fakeClock = new FakeClock(); + @Rule public final JpaUnitTestRule jpaRule = new JpaTestRules.Builder() .withInitScript(fileClassPath(getClass(), "test_schema.sql")) + .withClock(fakeClock) .buildUnitTestRule(); @Test @@ -55,7 +58,7 @@ public class JpaTransactionManagerImplTest { @Test public void getTransactionTime_throwsExceptionWhenNotInTransaction() { - FakeClock txnClock = jpaRule.getTxnClock(); + FakeClock txnClock = fakeClock; txnClock.advanceOneMilli(); assertThrows(PersistenceException.class, () -> jpaTm().getTransactionTime()); jpaTm().transact(() -> assertThat(jpaTm().getTransactionTime()).isEqualTo(txnClock.nowUtc())); diff --git a/core/src/test/java/google/registry/persistence/transaction/JpaTransactionManagerRule.java b/core/src/test/java/google/registry/persistence/transaction/JpaTransactionManagerRule.java index 844dc9004..cb73099c6 100644 --- a/core/src/test/java/google/registry/persistence/transaction/JpaTransactionManagerRule.java +++ b/core/src/test/java/google/registry/persistence/transaction/JpaTransactionManagerRule.java @@ -15,7 +15,6 @@ package google.registry.persistence.transaction; import static com.google.common.truth.Truth.assertThat; -import static org.joda.time.DateTimeZone.UTC; import static org.testcontainers.containers.PostgreSQLContainer.POSTGRESQL_PORT; import com.google.common.base.Charsets; @@ -27,8 +26,7 @@ import google.registry.persistence.HibernateSchemaExporter; import google.registry.persistence.NomulusPostgreSql; import google.registry.persistence.PersistenceModule; import google.registry.persistence.PersistenceXmlUtility; -import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationTestRule; -import google.registry.testing.FakeClock; +import google.registry.util.Clock; import java.io.File; import java.io.IOException; import java.io.UncheckedIOException; @@ -46,7 +44,6 @@ 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.time.DateTime; import org.junit.rules.ExternalResource; import org.testcontainers.containers.JdbcDatabaseContainer; import org.testcontainers.containers.PostgreSQLContainer; @@ -54,7 +51,8 @@ import org.testcontainers.containers.PostgreSQLContainer; /** * Base class of JUnit Rules to provision {@link JpaTransactionManagerImpl} backed by {@link * PostgreSQLContainer}. This class is not for direct use. Use specialized subclasses, {@link - * JpaIntegrationTestRule} or {@link JpaTestRules.JpaUnitTestRule} as befits the use case. + * google.registry.persistence.transaction.JpaTestRules.JpaIntegrationTestRule} or {@link + * JpaTestRules.JpaUnitTestRule} as befits the use case. * *

This rule also replaces the {@link JpaTransactionManagerImpl} provided by {@link * TransactionManagerFactory} with the {@link JpaTransactionManagerImpl} generated by the rule @@ -70,8 +68,7 @@ abstract class JpaTransactionManagerRule extends ExternalResource { // is documented in PSQL's official user guide. private static final String CONNECTION_BACKEND_TYPE = "client backend"; - private final DateTime now = DateTime.now(UTC); - private final FakeClock clock = new FakeClock(now); + private final Clock clock; private final Optional initScriptPath; private final ImmutableList extraEntityClasses; private final ImmutableMap userProperties; @@ -84,9 +81,11 @@ abstract class JpaTransactionManagerRule extends ExternalResource { private JpaTransactionManager cachedTm; protected JpaTransactionManagerRule( + Clock clock, Optional initScriptPath, ImmutableList extraEntityClasses, ImmutableMap userProperties) { + this.clock = clock; this.initScriptPath = initScriptPath; this.extraEntityClasses = extraEntityClasses; this.userProperties = userProperties; @@ -230,10 +229,4 @@ abstract class JpaTransactionManagerRule extends ExternalResource { extraEntityClasses.stream().map(Class::getName).forEach(descriptor::addClasses); return Bootstrap.getEntityManagerFactoryBuilder(descriptor, properties).build(); } - - /** Returns the {@link FakeClock} used by the underlying {@link JpaTransactionManagerImpl}. */ - public FakeClock getTxnClock() { - return clock; - } - } diff --git a/core/src/test/java/google/registry/persistence/transaction/TestCaseWatcher.java b/core/src/test/java/google/registry/persistence/transaction/TestCaseWatcher.java new file mode 100644 index 000000000..dbed29539 --- /dev/null +++ b/core/src/test/java/google/registry/persistence/transaction/TestCaseWatcher.java @@ -0,0 +1,47 @@ +// Copyright 2018 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.persistence.transaction; + +import static com.google.common.base.Preconditions.checkState; + +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; + +/** Keeps track of the current class and method under test. */ +public class TestCaseWatcher extends TestWatcher { + + private Description currentDescription; + + @Override + protected void starting(Description description) { + this.currentDescription = description; + } + + private void validateState() { + checkState( + currentDescription != null, + "Tests have not started yet. Make sure invocation is from inner rule or test code."); + } + + public String getTestClass() { + validateState(); + return currentDescription.getClassName(); + } + + public String getTestMethod() { + validateState(); + return currentDescription.getMethodName(); + } +} diff --git a/core/src/test/java/google/registry/schema/cursor/CursorDaoTest.java b/core/src/test/java/google/registry/schema/cursor/CursorDaoTest.java index 1b60573a9..0fc954c66 100644 --- a/core/src/test/java/google/registry/schema/cursor/CursorDaoTest.java +++ b/core/src/test/java/google/registry/schema/cursor/CursorDaoTest.java @@ -26,7 +26,7 @@ import com.google.common.testing.TestLogHandler; import google.registry.model.common.Cursor.CursorType; import google.registry.model.registry.Registry; import google.registry.persistence.transaction.JpaTestRules; -import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationTestRule; +import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule; import google.registry.testing.AppEngineRule; import google.registry.testing.FakeClock; import java.util.List; @@ -41,14 +41,14 @@ import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public class CursorDaoTest { - private FakeClock fakeClock = new FakeClock(); + private final FakeClock fakeClock = new FakeClock(); private final TestLogHandler logHandler = new TestLogHandler(); private final Logger loggerToIntercept = Logger.getLogger(CursorDao.class.getCanonicalName()); @Rule - public final JpaIntegrationTestRule jpaRule = - new JpaTestRules.Builder().buildIntegrationTestRule(); + public final JpaIntegrationWithCoverageRule jpaRule = + new JpaTestRules.Builder().withClock(fakeClock).buildIntegrationWithCoverageRule(); @Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build(); diff --git a/core/src/test/java/google/registry/schema/integration/SqlIntegrationMembershipTest.java b/core/src/test/java/google/registry/schema/integration/SqlIntegrationMembershipTest.java index 542c71e9b..67cabbae3 100644 --- a/core/src/test/java/google/registry/schema/integration/SqlIntegrationMembershipTest.java +++ b/core/src/test/java/google/registry/schema/integration/SqlIntegrationMembershipTest.java @@ -14,33 +14,33 @@ package google.registry.schema.integration; -import static com.google.common.truth.Truth.assertWithMessage; - import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import com.google.common.collect.Sets.SetView; -import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationTestRule; +import com.google.common.truth.Expect; +import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule; import io.github.classgraph.ClassGraph; import io.github.classgraph.ScanResult; import java.lang.reflect.Field; import java.util.stream.Stream; +import org.junit.ClassRule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.junit.runners.Suite.SuiteClasses; /** - * Verifies that all tests that depends on the Cloud SQL schema are included in the project's - * sqlIntegrationTest suite. Names of the test classes is set to the 'test.sqlIntergrationTests' - * system property as a comma-separated string. + * Verifies that {@link SqlIntegrationTestSuite} includes all integration tests for JPA entities and + * nothing else. The test suite is used in server/schema compatibility tests between releases. * - *

A test is deemed dependent on the SQL schema iff it has a field with type {@link - * JpaIntegrationTestRule}. + *

All JPA entity test classes are expected to have a field with type {@link + * JpaIntegrationWithCoverageRule}. */ -// TODO(weiminyu): consider generating a TestSuite class instead. @RunWith(JUnit4.class) public class SqlIntegrationMembershipTest { + @ClassRule public static final Expect expect = Expect.create(); + @Test public void sqlIntegrationMembershipComplete() { ImmutableSet sqlDependentTests; @@ -59,13 +59,15 @@ public class SqlIntegrationMembershipTest { .map(Class::getName) .collect(ImmutableSet.toImmutableSet()); SetView undeclaredTests = Sets.difference(sqlDependentTests, declaredTests); - assertWithMessage( + expect + .withMessage( "Undeclared sql-dependent tests found. " + "Please add them to SqlIntegrationTestSuite.java.") .that(undeclaredTests) .isEmpty(); SetView unnecessaryDeclarations = Sets.difference(declaredTests, sqlDependentTests); - assertWithMessage("Found tests that should not be included in SqlIntegrationTestSuite.java.") + expect + .withMessage("Found tests that should not be included in SqlIntegrationTestSuite.java.") .that(unnecessaryDeclarations) .isEmpty(); } @@ -74,7 +76,7 @@ public class SqlIntegrationMembershipTest { for (Class clazz = testClass; clazz != null; clazz = clazz.getSuperclass()) { if (Stream.of(clazz.getDeclaredFields()) .map(Field::getType) - .anyMatch(JpaIntegrationTestRule.class::equals)) { + .anyMatch(JpaIntegrationWithCoverageRule.class::equals)) { return true; } } diff --git a/core/src/test/java/google/registry/schema/integration/SqlIntegrationTestSuite.java b/core/src/test/java/google/registry/schema/integration/SqlIntegrationTestSuite.java index 60edb5262..1c474c1db 100644 --- a/core/src/test/java/google/registry/schema/integration/SqlIntegrationTestSuite.java +++ b/core/src/test/java/google/registry/schema/integration/SqlIntegrationTestSuite.java @@ -14,11 +14,11 @@ package google.registry.schema.integration; +import com.google.common.truth.Expect; import google.registry.model.registry.RegistryLockDaoTest; -import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationTestRule; +import google.registry.persistence.transaction.JpaEntityCoverage; 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; @@ -29,19 +29,24 @@ 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.AfterClass; +import org.junit.BeforeClass; +import org.junit.ClassRule; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; /** - * Groups all tests that may depends on Cloud SQL schema. They will be run for server-schema - * compatibility check. + * Groups all JPA entity tests in one suite for easy invocation. This suite is used for + * server/schema compatibility tests between releases. * - *

Schema dependency is approximated by the use of {@link JpaIntegrationTestRule}. + *

Every member class must use the {@link + * google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule} and have at + * least one test method that persists a JPA entity declared in persistence.xml. * - * @see SqlIntegrationMembershipTest + *

Membership of this suite is monitored by the checks in {@link #checkJpaEntityCoverage()} and + * {@link SqlIntegrationMembershipTest#sqlIntegrationMembershipComplete()}. */ -// TODO(weiminyu): refactor JpaTransactionManagerRule to eliminate false positives. @RunWith(Suite.class) @SuiteClasses({ ClaimsListDaoTest.class, @@ -51,7 +56,6 @@ import org.junit.runners.Suite.SuiteClasses; DomainLockUtilsTest.class, LockDomainCommandTest.class, PremiumListDaoTest.class, - PremiumListUtilsTest.class, RegistryLockDaoTest.class, RegistryLockGetActionTest.class, ReservedListDaoTest.class, @@ -59,4 +63,25 @@ import org.junit.runners.Suite.SuiteClasses; UpdatePremiumListActionTest.class, UpdateReservedListCommandTest.class }) -public class SqlIntegrationTestSuite {} +public class SqlIntegrationTestSuite { + + @ClassRule public static final Expect expect = Expect.create(); + + @BeforeClass + public static void initJpaEntityCoverage() { + JpaEntityCoverage.init(); + } + + @AfterClass + public static void checkJpaEntityCoverage() { + expect + .withMessage("Tests are missing for the following JPA entities:") + .that(JpaEntityCoverage.getUncoveredEntities()) + .isEmpty(); + expect + .withMessage( + "The following classes do not test JPA entities. Please remove them from this suite") + .that(JpaEntityCoverage.getIrrelevantTestClasses()) + .isEmpty(); + } +} diff --git a/core/src/test/java/google/registry/schema/tld/PremiumListDaoTest.java b/core/src/test/java/google/registry/schema/tld/PremiumListDaoTest.java index 82cf629d5..2b74d842d 100644 --- a/core/src/test/java/google/registry/schema/tld/PremiumListDaoTest.java +++ b/core/src/test/java/google/registry/schema/tld/PremiumListDaoTest.java @@ -29,8 +29,9 @@ import com.google.common.collect.ImmutableMap; import com.googlecode.objectify.Key; import google.registry.model.registry.Registry; import google.registry.persistence.transaction.JpaTestRules; -import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationTestRule; +import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule; import google.registry.testing.AppEngineRule; +import google.registry.testing.FakeClock; import java.math.BigDecimal; import java.util.Optional; import org.joda.money.CurrencyUnit; @@ -45,9 +46,11 @@ import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public class PremiumListDaoTest { + private final FakeClock fakeClock = new FakeClock(); + @Rule - public final JpaIntegrationTestRule jpaRule = - new JpaTestRules.Builder().buildIntegrationTestRule(); + public final JpaIntegrationWithCoverageRule jpaRule = + new JpaTestRules.Builder().withClock(fakeClock).buildIntegrationWithCoverageRule(); @Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build(); @@ -71,8 +74,7 @@ public class PremiumListDaoTest { assertThat(persistedListOpt).isPresent(); PremiumList persistedList = persistedListOpt.get(); assertThat(persistedList.getLabelsToPrices()).containsExactlyEntriesIn(TEST_PRICES); - assertThat(persistedList.getCreationTimestamp()) - .isEqualTo(jpaRule.getTxnClock().nowUtc()); + assertThat(persistedList.getCreationTimestamp()).isEqualTo(fakeClock.nowUtc()); }); } @@ -108,11 +110,9 @@ public class PremiumListDaoTest { BigDecimal.valueOf(0.01), "silver", BigDecimal.valueOf(30.03))); - assertThat(updatedList.getCreationTimestamp()) - .isEqualTo(jpaRule.getTxnClock().nowUtc()); + assertThat(updatedList.getCreationTimestamp()).isEqualTo(fakeClock.nowUtc()); assertThat(updatedList.getRevisionId()).isGreaterThan(firstRevisionId); - assertThat(updatedList.getCreationTimestamp()) - .isEqualTo(jpaRule.getTxnClock().nowUtc()); + assertThat(updatedList.getCreationTimestamp()).isEqualTo(fakeClock.nowUtc()); }); } diff --git a/core/src/test/java/google/registry/schema/tld/PremiumListUtilsTest.java b/core/src/test/java/google/registry/schema/tld/PremiumListUtilsTest.java index 39afdd810..1dd341afe 100644 --- a/core/src/test/java/google/registry/schema/tld/PremiumListUtilsTest.java +++ b/core/src/test/java/google/registry/schema/tld/PremiumListUtilsTest.java @@ -18,8 +18,6 @@ import static com.google.common.truth.Truth.assertThat; import static google.registry.schema.tld.PremiumListUtils.parseToPremiumList; import static org.junit.Assert.assertThrows; -import google.registry.persistence.transaction.JpaTestRules; -import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationTestRule; import google.registry.testing.AppEngineRule; import java.math.BigDecimal; import org.junit.Rule; @@ -33,10 +31,6 @@ public class PremiumListUtilsTest { @Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build(); - @Rule - public final JpaIntegrationTestRule jpaRule = - new JpaTestRules.Builder().buildIntegrationTestRule(); - @Test public void parseInputToPremiumList_works() { PremiumList premiumList = diff --git a/core/src/test/java/google/registry/schema/tld/ReservedListDaoTest.java b/core/src/test/java/google/registry/schema/tld/ReservedListDaoTest.java index 12eb25dab..5ebaa877e 100644 --- a/core/src/test/java/google/registry/schema/tld/ReservedListDaoTest.java +++ b/core/src/test/java/google/registry/schema/tld/ReservedListDaoTest.java @@ -20,8 +20,9 @@ import static google.registry.persistence.transaction.TransactionManagerFactory. import com.google.common.collect.ImmutableMap; import google.registry.model.registry.label.ReservationType; import google.registry.persistence.transaction.JpaTestRules; -import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationTestRule; +import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule; import google.registry.schema.tld.ReservedList.ReservedEntry; +import google.registry.testing.FakeClock; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -30,9 +31,12 @@ import org.junit.runners.JUnit4; /** Unit tests for {@link ReservedListDao}. */ @RunWith(JUnit4.class) public class ReservedListDaoTest { + + private final FakeClock fakeClock = new FakeClock(); + @Rule - public final JpaIntegrationTestRule jpaRule = - new JpaTestRules.Builder().buildIntegrationTestRule(); + public final JpaIntegrationWithCoverageRule jpaRule = + new JpaTestRules.Builder().withClock(fakeClock).buildIntegrationWithCoverageRule(); private static final ImmutableMap TEST_RESERVATIONS = ImmutableMap.of( @@ -56,8 +60,7 @@ public class ReservedListDaoTest { .getSingleResult(); assertThat(persistedList.getLabelsToReservations()) .containsExactlyEntriesIn(TEST_RESERVATIONS); - assertThat(persistedList.getCreationTimestamp()) - .isEqualTo(jpaRule.getTxnClock().nowUtc()); + assertThat(persistedList.getCreationTimestamp()).isEqualTo(fakeClock.nowUtc()); }); } @@ -74,7 +77,7 @@ public class ReservedListDaoTest { ReservedListDao.save(ReservedList.create("testlist", false, TEST_RESERVATIONS)); ReservedList persistedList = ReservedListDao.getLatestRevision("testlist").get(); assertThat(persistedList.getRevisionId()).isNotNull(); - assertThat(persistedList.getCreationTimestamp()).isEqualTo(jpaRule.getTxnClock().nowUtc()); + assertThat(persistedList.getCreationTimestamp()).isEqualTo(fakeClock.nowUtc()); assertThat(persistedList.getName()).isEqualTo("testlist"); assertThat(persistedList.getShouldPublish()).isFalse(); assertThat(persistedList.getLabelsToReservations()).containsExactlyEntriesIn(TEST_RESERVATIONS); @@ -91,7 +94,7 @@ public class ReservedListDaoTest { ReservedListDao.save(ReservedList.create("testlist", false, TEST_RESERVATIONS)); ReservedList persistedList = ReservedListDao.getLatestRevision("testlist").get(); assertThat(persistedList.getRevisionId()).isNotNull(); - assertThat(persistedList.getCreationTimestamp()).isEqualTo(jpaRule.getTxnClock().nowUtc()); + assertThat(persistedList.getCreationTimestamp()).isEqualTo(fakeClock.nowUtc()); assertThat(persistedList.getName()).isEqualTo("testlist"); assertThat(persistedList.getShouldPublish()).isFalse(); assertThat(persistedList.getLabelsToReservations()).containsExactlyEntriesIn(TEST_RESERVATIONS); @@ -102,7 +105,7 @@ public class ReservedListDaoTest { ReservedListDao.save(ReservedList.create("testlist", false, TEST_RESERVATIONS)); ReservedList persistedList = ReservedListDao.getLatestRevisionCached("testlist").get(); assertThat(persistedList.getRevisionId()).isNotNull(); - assertThat(persistedList.getCreationTimestamp()).isEqualTo(jpaRule.getTxnClock().nowUtc()); + assertThat(persistedList.getCreationTimestamp()).isEqualTo(fakeClock.nowUtc()); assertThat(persistedList.getName()).isEqualTo("testlist"); assertThat(persistedList.getShouldPublish()).isFalse(); assertThat(persistedList.getLabelsToReservations()).containsExactlyEntriesIn(TEST_RESERVATIONS); diff --git a/core/src/test/java/google/registry/schema/tmch/ClaimsListDaoTest.java b/core/src/test/java/google/registry/schema/tmch/ClaimsListDaoTest.java index d038d0bf6..1b2db21bb 100644 --- a/core/src/test/java/google/registry/schema/tmch/ClaimsListDaoTest.java +++ b/core/src/test/java/google/registry/schema/tmch/ClaimsListDaoTest.java @@ -18,7 +18,7 @@ import static com.google.common.truth.Truth.assertThat; import com.google.common.collect.ImmutableMap; import google.registry.persistence.transaction.JpaTestRules; -import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationTestRule; +import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule; import google.registry.testing.FakeClock; import org.junit.Rule; import org.junit.Test; @@ -29,11 +29,11 @@ import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public class ClaimsListDaoTest { - private FakeClock fakeClock = new FakeClock(); + private final FakeClock fakeClock = new FakeClock(); @Rule - public final JpaIntegrationTestRule jpaRule = - new JpaTestRules.Builder().buildIntegrationTestRule(); + public final JpaIntegrationWithCoverageRule jpaRule = + new JpaTestRules.Builder().withClock(fakeClock).buildIntegrationWithCoverageRule(); @Test public void trySave_insertsClaimsListSuccessfully() { @@ -42,7 +42,7 @@ public class ClaimsListDaoTest { ClaimsListDao.trySave(claimsList); ClaimsList insertedClaimsList = ClaimsListDao.getLatestRevision().get(); assertClaimsListEquals(claimsList, insertedClaimsList); - assertThat(insertedClaimsList.getCreationTimestamp()).isEqualTo(jpaRule.getTxnClock().nowUtc()); + assertThat(insertedClaimsList.getCreationTimestamp()).isEqualTo(fakeClock.nowUtc()); } @Test diff --git a/core/src/test/java/google/registry/tools/CreateOrUpdateReservedListCommandTestCase.java b/core/src/test/java/google/registry/tools/CreateOrUpdateReservedListCommandTestCase.java index 9f7cb0bc7..761a16c82 100644 --- a/core/src/test/java/google/registry/tools/CreateOrUpdateReservedListCommandTestCase.java +++ b/core/src/test/java/google/registry/tools/CreateOrUpdateReservedListCommandTestCase.java @@ -26,9 +26,10 @@ import com.google.common.io.Files; import com.google.common.truth.Truth8; import google.registry.model.registry.label.ReservedList; import google.registry.persistence.transaction.JpaTestRules; -import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationTestRule; +import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule; import google.registry.schema.tld.ReservedList.ReservedEntry; import google.registry.schema.tld.ReservedListDao; +import google.registry.testing.FakeClock; import java.io.File; import java.io.IOException; import java.util.Map; @@ -45,9 +46,11 @@ import org.junit.Test; public abstract class CreateOrUpdateReservedListCommandTestCase extends CommandTestCase { + private final FakeClock fakeClock = new FakeClock(); + @Rule - public final JpaIntegrationTestRule jpaRule = - new JpaTestRules.Builder().buildIntegrationTestRule(); + public final JpaIntegrationWithCoverageRule jpaRule = + new JpaTestRules.Builder().withClock(fakeClock).buildIntegrationWithCoverageRule(); String reservedTermsPath; String invalidReservedTermsPath; @@ -112,7 +115,7 @@ public abstract class CreateOrUpdateReservedListCommandTestCase getCloudSqlReservedList("xn--q9jyb4c_common-reserved"); assertThat(persistedList.getName()).isEqualTo("xn--q9jyb4c_common-reserved"); assertThat(persistedList.getShouldPublish()).isTrue(); - assertThat(persistedList.getCreationTimestamp()).isEqualTo(jpaRule.getTxnClock().nowUtc()); + assertThat(persistedList.getCreationTimestamp()).isEqualTo(fakeClock.nowUtc()); assertThat(persistedList.getLabelsToReservations()) .containsExactly( "baddies", diff --git a/core/src/test/java/google/registry/tools/DomainLockUtilsTest.java b/core/src/test/java/google/registry/tools/DomainLockUtilsTest.java index b8abd51e3..b854d63b7 100644 --- a/core/src/test/java/google/registry/tools/DomainLockUtilsTest.java +++ b/core/src/test/java/google/registry/tools/DomainLockUtilsTest.java @@ -34,7 +34,7 @@ import google.registry.model.registry.Registry; import google.registry.model.registry.RegistryLockDao; import google.registry.model.reporting.HistoryEntry; import google.registry.persistence.transaction.JpaTestRules; -import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationTestRule; +import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule; import google.registry.schema.domain.RegistryLock; import google.registry.testing.AppEngineRule; import google.registry.testing.DatastoreHelper; @@ -56,6 +56,8 @@ public final class DomainLockUtilsTest { private static final String DOMAIN_NAME = "example.tld"; private static final String POC_ID = "marla.singer@example.com"; + private final FakeClock clock = new FakeClock(); + @Rule public final AppEngineRule appEngineRule = AppEngineRule.builder() @@ -64,10 +66,8 @@ public final class DomainLockUtilsTest { .build(); @Rule - public final JpaIntegrationTestRule jpaRule = - new JpaTestRules.Builder().buildIntegrationTestRule(); - - private final FakeClock clock = jpaRule.getTxnClock(); + public final JpaIntegrationWithCoverageRule jpaRule = + new JpaTestRules.Builder().withClock(clock).buildIntegrationWithCoverageRule(); private DomainBase domain; diff --git a/core/src/test/java/google/registry/tools/LockDomainCommandTest.java b/core/src/test/java/google/registry/tools/LockDomainCommandTest.java index f915da835..7e25607bb 100644 --- a/core/src/test/java/google/registry/tools/LockDomainCommandTest.java +++ b/core/src/test/java/google/registry/tools/LockDomainCommandTest.java @@ -29,7 +29,7 @@ import google.registry.model.domain.DomainBase; import google.registry.model.registrar.Registrar.Type; import google.registry.model.registry.RegistryLockDao; import google.registry.persistence.transaction.JpaTestRules; -import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationTestRule; +import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule; import google.registry.testing.FakeClock; import java.util.ArrayList; import java.util.List; @@ -42,8 +42,8 @@ import org.junit.Test; public class LockDomainCommandTest extends CommandTestCase { @Rule - public final JpaIntegrationTestRule jpaRule = - new JpaTestRules.Builder().buildIntegrationTestRule(); + public final JpaIntegrationWithCoverageRule jpaRule = + new JpaTestRules.Builder().buildIntegrationWithCoverageRule(); @Before public void before() { diff --git a/core/src/test/java/google/registry/tools/UnlockDomainCommandTest.java b/core/src/test/java/google/registry/tools/UnlockDomainCommandTest.java index cf55bb019..a59401392 100644 --- a/core/src/test/java/google/registry/tools/UnlockDomainCommandTest.java +++ b/core/src/test/java/google/registry/tools/UnlockDomainCommandTest.java @@ -31,7 +31,7 @@ import google.registry.model.domain.DomainBase; import google.registry.model.registrar.Registrar.Type; import google.registry.model.registry.RegistryLockDao; import google.registry.persistence.transaction.JpaTestRules; -import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationTestRule; +import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule; import google.registry.schema.domain.RegistryLock; import google.registry.testing.FakeClock; import java.util.ArrayList; @@ -45,8 +45,8 @@ import org.junit.Test; public class UnlockDomainCommandTest extends CommandTestCase { @Rule - public final JpaIntegrationTestRule jpaRule = - new JpaTestRules.Builder().buildIntegrationTestRule(); + public final JpaIntegrationWithCoverageRule jpaRule = + new JpaTestRules.Builder().buildIntegrationWithCoverageRule(); @Before public void before() { diff --git a/core/src/test/java/google/registry/tools/server/CreatePremiumListActionTest.java b/core/src/test/java/google/registry/tools/server/CreatePremiumListActionTest.java index 233f48033..0d3b9c5a8 100644 --- a/core/src/test/java/google/registry/tools/server/CreatePremiumListActionTest.java +++ b/core/src/test/java/google/registry/tools/server/CreatePremiumListActionTest.java @@ -25,7 +25,7 @@ import static javax.servlet.http.HttpServletResponse.SC_OK; import google.registry.model.registry.Registry; import google.registry.model.registry.label.PremiumList; import google.registry.persistence.transaction.JpaTestRules; -import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationTestRule; +import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule; import google.registry.testing.AppEngineRule; import google.registry.testing.FakeJsonResponse; import org.joda.money.Money; @@ -42,8 +42,8 @@ import org.junit.runners.JUnit4; public class CreatePremiumListActionTest { @Rule - public final JpaIntegrationTestRule jpaRule = - new JpaTestRules.Builder().buildIntegrationTestRule(); + public final JpaIntegrationWithCoverageRule jpaRule = + new JpaTestRules.Builder().buildIntegrationWithCoverageRule(); @Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build(); CreatePremiumListAction action; diff --git a/core/src/test/java/google/registry/tools/server/UpdatePremiumListActionTest.java b/core/src/test/java/google/registry/tools/server/UpdatePremiumListActionTest.java index 178ba3238..5d09f95d7 100644 --- a/core/src/test/java/google/registry/tools/server/UpdatePremiumListActionTest.java +++ b/core/src/test/java/google/registry/tools/server/UpdatePremiumListActionTest.java @@ -27,7 +27,7 @@ import static javax.servlet.http.HttpServletResponse.SC_OK; import google.registry.model.registry.Registry; import google.registry.model.registry.label.PremiumList; import google.registry.persistence.transaction.JpaTestRules; -import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationTestRule; +import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule; import google.registry.schema.tld.PremiumListDao; import google.registry.testing.AppEngineRule; import google.registry.testing.DatastoreHelper; @@ -49,8 +49,8 @@ public class UpdatePremiumListActionTest { @Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build(); @Rule - public final JpaIntegrationTestRule jpaRule = - new JpaTestRules.Builder().buildIntegrationTestRule(); + public final JpaIntegrationWithCoverageRule jpaRule = + new JpaTestRules.Builder().buildIntegrationWithCoverageRule(); UpdatePremiumListAction action; FakeJsonResponse response; diff --git a/core/src/test/java/google/registry/ui/server/registrar/RegistryLockGetActionTest.java b/core/src/test/java/google/registry/ui/server/registrar/RegistryLockGetActionTest.java index 0fb8724b1..4a4ddda58 100644 --- a/core/src/test/java/google/registry/ui/server/registrar/RegistryLockGetActionTest.java +++ b/core/src/test/java/google/registry/ui/server/registrar/RegistryLockGetActionTest.java @@ -31,7 +31,7 @@ import com.google.common.collect.ImmutableSetMultimap; import com.google.gson.Gson; import google.registry.model.registry.RegistryLockDao; import google.registry.persistence.transaction.JpaTestRules; -import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationTestRule; +import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule; import google.registry.request.Action.Method; import google.registry.request.auth.AuthLevel; import google.registry.request.auth.AuthResult; @@ -39,6 +39,7 @@ import google.registry.request.auth.AuthenticatedRegistrarAccessor; import google.registry.request.auth.UserAuthInfo; import google.registry.schema.domain.RegistryLock; import google.registry.testing.AppEngineRule; +import google.registry.testing.FakeClock; import google.registry.testing.FakeResponse; import java.util.Map; import java.util.Optional; @@ -58,11 +59,13 @@ public final class RegistryLockGetActionTest { private static final Gson GSON = new Gson(); + private final FakeClock fakeClock = new FakeClock(); + @Rule public final AppEngineRule appEngineRule = AppEngineRule.builder().withDatastore().build(); @Rule - public final JpaIntegrationTestRule jpaRule = - new JpaTestRules.Builder().buildIntegrationTestRule(); + public final JpaIntegrationWithCoverageRule jpaRule = + new JpaTestRules.Builder().withClock(fakeClock).buildIntegrationWithCoverageRule(); @Rule public final MockitoRule mocks = MockitoJUnit.rule(); @@ -75,7 +78,7 @@ public final class RegistryLockGetActionTest { @Before public void setup() { - jpaRule.getTxnClock().setTo(DateTime.parse("2000-06-08T22:00:00.0Z")); + fakeClock.setTo(DateTime.parse("2000-06-08T22:00:00.0Z")); authResult = AuthResult.create(AuthLevel.USER, UserAuthInfo.create(user, false)); accessor = AuthenticatedRegistrarAccessor.createForTesting( @@ -96,9 +99,9 @@ public final class RegistryLockGetActionTest { .setRegistrarId("TheRegistrar") .setVerificationCode(UUID.randomUUID().toString()) .setRegistrarPocId("johndoe@theregistrar.com") - .setLockCompletionTimestamp(jpaRule.getTxnClock().nowUtc()) + .setLockCompletionTimestamp(fakeClock.nowUtc()) .build(); - jpaRule.getTxnClock().advanceOneMilli(); + fakeClock.advanceOneMilli(); RegistryLock adminLock = new RegistryLock.Builder() .setRepoId("repoId") @@ -106,7 +109,7 @@ public final class RegistryLockGetActionTest { .setRegistrarId("TheRegistrar") .setVerificationCode(UUID.randomUUID().toString()) .isSuperuser(true) - .setLockCompletionTimestamp(jpaRule.getTxnClock().nowUtc()) + .setLockCompletionTimestamp(fakeClock.nowUtc()) .build(); RegistryLock incompleteLock = new RegistryLock.Builder() @@ -124,9 +127,9 @@ public final class RegistryLockGetActionTest { .setRegistrarId("TheRegistrar") .setRegistrarPocId("johndoe@theregistrar.com") .setVerificationCode(UUID.randomUUID().toString()) - .setLockCompletionTimestamp(jpaRule.getTxnClock().nowUtc()) - .setUnlockRequestTimestamp(jpaRule.getTxnClock().nowUtc()) - .setUnlockCompletionTimestamp(jpaRule.getTxnClock().nowUtc()) + .setLockCompletionTimestamp(fakeClock.nowUtc()) + .setUnlockRequestTimestamp(fakeClock.nowUtc()) + .setUnlockCompletionTimestamp(fakeClock.nowUtc()) .build(); RegistryLockDao.save(regularLock);