From ab0410422c9b7e3f8c91486cfdda29bac365a85e Mon Sep 17 00:00:00 2001 From: Weimin Yu Date: Thu, 23 Jan 2020 16:41:27 -0500 Subject: [PATCH] Require tests on all declared JPA entities (#456) * Require tests on all declared JPA entities The JPA entity classes declared in persistence.xml reflects JPA's view of the database. The view must be compatible, though not always consistent with the actual schema. By defining and using a new JpaIntegrationWithCoverageRule, this change verifies that all JPA entities in persistence.xml are included in some tests in the SqlIntegrationTestSuite. Also removed one test from SqlIntegrationTestSuite since it does not use Cloud SQL. Lastly, global resources such as clock should be provided to a test fixture. Having one fixture creating its own makes it harder to use in a multi-system integration test. This change refactored JpaTransactionManagerRule to take a user provided clock. --- .../model/registry/RegistryLockDaoTest.java | 58 +++++---- .../CreateAutoTimestampConverterTest.java | 10 +- .../UpdateAutoTimestampConverterTest.java | 14 ++- .../transaction/JpaEntityCoverage.java | 115 ++++++++++++++++++ .../persistence/transaction/JpaTestRules.java | 76 ++++++++++-- .../JpaTransactionManagerImplTest.java | 5 +- .../JpaTransactionManagerRule.java | 19 +-- .../transaction/TestCaseWatcher.java | 47 +++++++ .../registry/schema/cursor/CursorDaoTest.java | 8 +- .../SqlIntegrationMembershipTest.java | 26 ++-- .../integration/SqlIntegrationTestSuite.java | 43 +++++-- .../schema/tld/PremiumListDaoTest.java | 18 +-- .../schema/tld/PremiumListUtilsTest.java | 6 - .../schema/tld/ReservedListDaoTest.java | 19 +-- .../schema/tmch/ClaimsListDaoTest.java | 10 +- ...teOrUpdateReservedListCommandTestCase.java | 11 +- .../registry/tools/DomainLockUtilsTest.java | 10 +- .../registry/tools/LockDomainCommandTest.java | 6 +- .../tools/UnlockDomainCommandTest.java | 6 +- .../server/CreatePremiumListActionTest.java | 6 +- .../server/UpdatePremiumListActionTest.java | 6 +- .../registrar/RegistryLockGetActionTest.java | 23 ++-- 22 files changed, 397 insertions(+), 145 deletions(-) create mode 100644 core/src/test/java/google/registry/persistence/transaction/JpaEntityCoverage.java create mode 100644 core/src/test/java/google/registry/persistence/transaction/TestCaseWatcher.java 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);