mirror of
https://github.com/google/nomulus
synced 2026-09-01 21:57:02 +00:00
Delete code relating to SQL init and scheduling (#1661)
One of the more significant changes introduced in this PR is that we use SQL as the backing database in all tests unless otherwise specified, e.g. by using the TmOverrideExtension. We change various ofy-related tests to use this. This includes various changes: - Deletion of SqlEntity/DatastoreEntity and related classes. Includes any necessary changes because of that (e.g. getting a nice SQL key on error in RegistryJpaIO). - Deletion of classes that used libraries from the init-sql code (RefreshDnsOnHostRenameAction) - Removal of the JpaTransactionManager's backup implementation - Modification of RegistryJpaWriteTest to not use init-sql code - Removal of the Transaction class and related classes, however it does not remove the TransactionEntity class as that would require DB changes - Removal of anything related to the actual usage of the database migration schedule or read-only phases - Various test changes and fixes to account for the differences in SQL (like how foreign keys need to exist) This deliberately doesn't do anything to alter the objects actually stored in the DB yet, just how we use them
This commit is contained in:
@@ -29,8 +29,10 @@ import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.CloudTasksHelper;
|
||||
import google.registry.testing.CloudTasksHelper.TaskMatcher;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
@@ -39,6 +41,10 @@ public class CommitLogCheckpointActionTest {
|
||||
|
||||
private static final String QUEUE_NAME = "export-commits";
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withOfy();
|
||||
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withDatastoreAndCloudSql().withTaskQueue().build();
|
||||
|
||||
@@ -26,10 +26,12 @@ import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeResponse;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import google.registry.testing.mapreduce.MapreduceTestCase;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
@@ -37,6 +39,10 @@ import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
public class DeleteOldCommitLogsActionTest
|
||||
extends MapreduceTestCase<DeleteOldCommitLogsAction> {
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withOfy();
|
||||
|
||||
private final FakeClock clock = new FakeClock(DateTime.parse("2000-01-01TZ"));
|
||||
private final FakeResponse response = new FakeResponse();
|
||||
private ContactResource contact;
|
||||
|
||||
@@ -36,15 +36,21 @@ import google.registry.model.ofy.CommitLogManifest;
|
||||
import google.registry.model.ofy.CommitLogMutation;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.TestObject;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import java.util.List;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link ExportCommitLogDiffAction}. */
|
||||
public class ExportCommitLogDiffActionTest {
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withOfy();
|
||||
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder()
|
||||
|
||||
@@ -1,279 +0,0 @@
|
||||
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.batch;
|
||||
|
||||
import static com.google.appengine.api.taskqueue.QueueFactory.getQueue;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth8.assertThat;
|
||||
import static google.registry.batch.AsyncTaskEnqueuer.PARAM_HOST_KEY;
|
||||
import static google.registry.batch.AsyncTaskEnqueuer.PARAM_REQUESTED_TIME;
|
||||
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_HOST_RENAME;
|
||||
import static google.registry.batch.AsyncTaskMetrics.OperationType.DNS_REFRESH;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.newDomainBase;
|
||||
import static google.registry.testing.DatabaseHelper.newHostResource;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveHost;
|
||||
import static google.registry.testing.DatabaseHelper.persistDeletedHost;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static google.registry.testing.TaskQueueHelper.assertDnsTasksEnqueued;
|
||||
import static google.registry.testing.TaskQueueHelper.assertNoDnsTasksEnqueued;
|
||||
import static google.registry.testing.TaskQueueHelper.assertNoTasksEnqueued;
|
||||
import static google.registry.testing.TaskQueueHelper.assertTasksEnqueued;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static org.joda.time.Duration.millis;
|
||||
import static org.joda.time.Duration.standardDays;
|
||||
import static org.joda.time.Duration.standardHours;
|
||||
import static org.joda.time.Duration.standardSeconds;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import google.registry.batch.AsyncTaskMetrics.OperationResult;
|
||||
import google.registry.batch.RefreshDnsOnHostRenameAction.RefreshDnsOnHostRenameReducer;
|
||||
import google.registry.dns.DnsQueue;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.model.server.Lock;
|
||||
import google.registry.testing.CloudTasksHelper;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeResponse;
|
||||
import google.registry.testing.FakeSleeper;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.testing.TaskQueueHelper.TaskMatcher;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import google.registry.testing.TestSqlOnly;
|
||||
import google.registry.testing.mapreduce.MapreduceTestCase;
|
||||
import google.registry.util.RequestStatusChecker;
|
||||
import google.registry.util.Retrier;
|
||||
import google.registry.util.Sleeper;
|
||||
import google.registry.util.SystemSleeper;
|
||||
import java.util.Optional;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.mockito.Mock;
|
||||
|
||||
/** Unit tests for {@link RefreshDnsOnHostRenameAction}. */
|
||||
@DualDatabaseTest
|
||||
public class RefreshDnsOnHostRenameActionTest
|
||||
extends MapreduceTestCase<RefreshDnsOnHostRenameAction> {
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
private AsyncTaskEnqueuer enqueuer;
|
||||
private final FakeClock clock = new FakeClock(DateTime.parse("2015-01-15T11:22:33Z"));
|
||||
private final FakeResponse fakeResponse = new FakeResponse();
|
||||
@Mock private RequestStatusChecker requestStatusChecker;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
createTld("tld");
|
||||
enqueuer =
|
||||
AsyncTaskEnqueuerTest.createForTesting(
|
||||
new CloudTasksHelper(clock).getTestCloudTasksUtils(), clock, Duration.ZERO);
|
||||
AsyncTaskMetrics asyncTaskMetricsMock = mock(AsyncTaskMetrics.class);
|
||||
action = new RefreshDnsOnHostRenameAction();
|
||||
action.asyncTaskMetrics = asyncTaskMetricsMock;
|
||||
inject.setStaticField(
|
||||
RefreshDnsOnHostRenameReducer.class, "asyncTaskMetrics", asyncTaskMetricsMock);
|
||||
action.clock = clock;
|
||||
action.mrRunner = makeDefaultRunner();
|
||||
action.pullQueue = getQueue(QUEUE_ASYNC_HOST_RENAME);
|
||||
action.dnsQueue = DnsQueue.createForTesting(clock);
|
||||
action.requestStatusChecker = requestStatusChecker;
|
||||
action.response = fakeResponse;
|
||||
action.retrier = new Retrier(new FakeSleeper(clock), 1);
|
||||
when(requestStatusChecker.getLogId()).thenReturn("requestId");
|
||||
when(requestStatusChecker.isRunning(anyString()))
|
||||
.thenThrow(new AssertionError("Should not be called"));
|
||||
}
|
||||
|
||||
private void runAction() throws Exception {
|
||||
clock.advanceOneMilli();
|
||||
// Use hard sleeps to ensure that the tasks are enqueued properly and will be leased.
|
||||
Sleeper sleeper = new SystemSleeper();
|
||||
sleeper.sleep(millis(50));
|
||||
action.run();
|
||||
sleeper.sleep(millis(50));
|
||||
executeTasksUntilEmpty("mapreduce", clock);
|
||||
sleeper.sleep(millis(50));
|
||||
clock.advanceBy(standardSeconds(5));
|
||||
tm().clearSessionCache();
|
||||
}
|
||||
|
||||
/** Kicks off, but does not run, the mapreduce tasks. Useful for testing validation/setup. */
|
||||
private void enqueueMapreduceOnly() {
|
||||
clock.advanceOneMilli();
|
||||
action.run();
|
||||
clock.advanceBy(standardSeconds(5));
|
||||
tm().clearSessionCache();
|
||||
}
|
||||
|
||||
@TestSqlOnly
|
||||
void testFailure_dnsUpdateEnqueueFailed() throws Exception {
|
||||
HostResource host = persistActiveHost("ns1.example.tld");
|
||||
persistResource(newDomainBase("example.tld", host));
|
||||
persistResource(newDomainBase("otherexample.tld", host));
|
||||
persistResource(newDomainBase("untouched.tld", persistActiveHost("ns2.example.tld")));
|
||||
DateTime timeEnqueued = clock.nowUtc();
|
||||
enqueuer.enqueueAsyncDnsRefresh(host, timeEnqueued);
|
||||
DnsQueue mockedQueue = mock(DnsQueue.class);
|
||||
action.dnsQueue = mockedQueue;
|
||||
when(mockedQueue.addDomainRefreshTask(anyString()))
|
||||
.thenThrow(new RuntimeException("Cannot enqueue task."));
|
||||
runAction();
|
||||
assertNoDnsTasksEnqueued();
|
||||
assertTasksEnqueued(
|
||||
QUEUE_ASYNC_HOST_RENAME,
|
||||
new TaskMatcher()
|
||||
.param(PARAM_HOST_KEY, host.createVKey().stringify())
|
||||
.param(PARAM_REQUESTED_TIME, timeEnqueued.toString()));
|
||||
verify(action.asyncTaskMetrics).recordDnsRefreshBatchSize(1L);
|
||||
verifyNoMoreInteractions(action.asyncTaskMetrics);
|
||||
assertThat(fakeResponse.getStatus()).isEqualTo(HttpStatus.SC_INTERNAL_SERVER_ERROR);
|
||||
assertThat(acquireLock()).isPresent();
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testSuccess_dnsUpdateEnqueued() throws Exception {
|
||||
HostResource host = persistActiveHost("ns1.example.tld");
|
||||
persistResource(newDomainBase("example.tld", host));
|
||||
persistResource(newDomainBase("otherexample.tld", host));
|
||||
persistResource(newDomainBase("untouched.tld", persistActiveHost("ns2.example.tld")));
|
||||
DateTime timeEnqueued = clock.nowUtc();
|
||||
enqueuer.enqueueAsyncDnsRefresh(host, timeEnqueued);
|
||||
runAction();
|
||||
assertDnsTasksEnqueued("example.tld", "otherexample.tld");
|
||||
assertNoTasksEnqueued(QUEUE_ASYNC_HOST_RENAME);
|
||||
verify(action.asyncTaskMetrics).recordDnsRefreshBatchSize(1L);
|
||||
verify(action.asyncTaskMetrics)
|
||||
.recordAsyncFlowResult(DNS_REFRESH, OperationResult.SUCCESS, timeEnqueued);
|
||||
verifyNoMoreInteractions(action.asyncTaskMetrics);
|
||||
assertThat(acquireLock()).isPresent();
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testSuccess_multipleHostsProcessedInBatch() throws Exception {
|
||||
HostResource host1 = persistActiveHost("ns1.example.tld");
|
||||
HostResource host2 = persistActiveHost("ns2.example.tld");
|
||||
HostResource host3 = persistActiveHost("ns3.example.tld");
|
||||
persistResource(newDomainBase("example1.tld", host1, host2));
|
||||
persistResource(newDomainBase("example2.tld", host2));
|
||||
persistResource(newDomainBase("example3.tld", host3));
|
||||
DateTime timeEnqueued = clock.nowUtc();
|
||||
DateTime laterTimeEnqueued = timeEnqueued.plus(standardSeconds(10));
|
||||
enqueuer.enqueueAsyncDnsRefresh(host1, timeEnqueued);
|
||||
enqueuer.enqueueAsyncDnsRefresh(host2, timeEnqueued);
|
||||
enqueuer.enqueueAsyncDnsRefresh(host3, laterTimeEnqueued);
|
||||
runAction();
|
||||
assertDnsTasksEnqueued("example1.tld", "example2.tld", "example3.tld");
|
||||
assertNoTasksEnqueued(QUEUE_ASYNC_HOST_RENAME);
|
||||
verify(action.asyncTaskMetrics).recordDnsRefreshBatchSize(3L);
|
||||
verify(action.asyncTaskMetrics, times(2))
|
||||
.recordAsyncFlowResult(DNS_REFRESH, OperationResult.SUCCESS, timeEnqueued);
|
||||
verify(action.asyncTaskMetrics)
|
||||
.recordAsyncFlowResult(DNS_REFRESH, OperationResult.SUCCESS, laterTimeEnqueued);
|
||||
verifyNoMoreInteractions(action.asyncTaskMetrics);
|
||||
assertThat(acquireLock()).isPresent();
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testSuccess_deletedHost_doesntTriggerDnsRefresh() throws Exception {
|
||||
HostResource host = persistDeletedHost("ns11.fakesss.tld", clock.nowUtc().minusDays(4));
|
||||
persistResource(newDomainBase("example1.tld", host));
|
||||
DateTime timeEnqueued = clock.nowUtc();
|
||||
enqueuer.enqueueAsyncDnsRefresh(host, timeEnqueued);
|
||||
runAction();
|
||||
assertNoDnsTasksEnqueued();
|
||||
assertNoTasksEnqueued(QUEUE_ASYNC_HOST_RENAME);
|
||||
verify(action.asyncTaskMetrics).recordDnsRefreshBatchSize(1L);
|
||||
verify(action.asyncTaskMetrics)
|
||||
.recordAsyncFlowResult(DNS_REFRESH, OperationResult.STALE, timeEnqueued);
|
||||
verifyNoMoreInteractions(action.asyncTaskMetrics);
|
||||
assertThat(acquireLock()).isPresent();
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testSuccess_noDnsTasksForDeletedDomain() throws Exception {
|
||||
HostResource renamedHost = persistActiveHost("ns1.example.tld");
|
||||
persistResource(
|
||||
newDomainBase("example.tld", renamedHost)
|
||||
.asBuilder()
|
||||
.setDeletionTime(START_OF_TIME)
|
||||
.build());
|
||||
enqueuer.enqueueAsyncDnsRefresh(renamedHost, clock.nowUtc());
|
||||
runAction();
|
||||
assertNoDnsTasksEnqueued();
|
||||
assertNoTasksEnqueued(QUEUE_ASYNC_HOST_RENAME);
|
||||
assertThat(acquireLock()).isPresent();
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testRun_hostDoesntExist_delaysTask() {
|
||||
HostResource host = newHostResource("ns1.example.tld");
|
||||
enqueuer.enqueueAsyncDnsRefresh(host, clock.nowUtc());
|
||||
enqueueMapreduceOnly();
|
||||
assertNoDnsTasksEnqueued();
|
||||
assertTasksEnqueued(
|
||||
QUEUE_ASYNC_HOST_RENAME,
|
||||
new TaskMatcher()
|
||||
.etaDelta(standardHours(23), standardHours(25))
|
||||
.param(PARAM_HOST_KEY, host.createVKey().stringify()));
|
||||
assertThat(acquireLock()).isPresent();
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void test_cannotAcquireLock() {
|
||||
// Make lock acquisition fail.
|
||||
acquireLock();
|
||||
enqueueMapreduceOnly();
|
||||
assertThat(fakeResponse.getPayload()).isEqualTo("Can't acquire lock; aborting.");
|
||||
assertNoDnsTasksEnqueued();
|
||||
assertThat(acquireLock()).isEmpty();
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void test_mapreduceHasWorkToDo_lockIsAcquired() {
|
||||
HostResource host = persistActiveHost("ns1.example.tld");
|
||||
enqueuer.enqueueAsyncDnsRefresh(host, clock.nowUtc());
|
||||
enqueueMapreduceOnly();
|
||||
assertThat(acquireLock()).isEmpty();
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void test_noTasksToLease_releasesLockImmediately() {
|
||||
enqueueMapreduceOnly();
|
||||
assertNoDnsTasksEnqueued();
|
||||
assertNoTasksEnqueued(QUEUE_ASYNC_HOST_RENAME);
|
||||
// If the Lock was correctly released, then we can acquire it now.
|
||||
assertThat(acquireLock()).isPresent();
|
||||
}
|
||||
|
||||
private Optional<Lock> acquireLock() {
|
||||
return Lock.acquire(
|
||||
RefreshDnsOnHostRenameAction.class.getSimpleName(),
|
||||
null,
|
||||
standardDays(30),
|
||||
requestStatusChecker,
|
||||
false);
|
||||
}
|
||||
}
|
||||
@@ -24,10 +24,13 @@ import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.testing.FakeResponse;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import google.registry.testing.mapreduce.MapreduceTestCase;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link ResaveAllEppResourcesAction}. */
|
||||
// No longer needed in SQL. Subject to future removal.
|
||||
@@ -35,6 +38,10 @@ import org.junit.jupiter.api.Test;
|
||||
@DeleteAfterMigration
|
||||
class ResaveAllEppResourcesActionTest extends MapreduceTestCase<ResaveAllEppResourcesAction> {
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withOfy();
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
action = new ResaveAllEppResourcesAction();
|
||||
|
||||
@@ -18,30 +18,18 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.ImmutableObjectSubject.immutableObjectCorrespondence;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.testing.DatabaseHelper.newContactResource;
|
||||
import static google.registry.testing.DatabaseHelper.putInDb;
|
||||
|
||||
import com.google.appengine.api.datastore.Entity;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.backup.VersionedEntity;
|
||||
import google.registry.beam.TestPipelineExtension;
|
||||
import google.registry.beam.initsql.BackupTestStore;
|
||||
import google.registry.beam.initsql.InitSqlTestUtils;
|
||||
import google.registry.beam.initsql.Transforms;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import java.io.Serializable;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.beam.sdk.transforms.Create;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
@@ -49,17 +37,13 @@ import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
/** Unit test for {@link RegistryJpaIO.Write}. */
|
||||
class RegistryJpaWriteTest implements Serializable {
|
||||
|
||||
private static final DateTime START_TIME = DateTime.parse("2000-01-01T00:00:00.0Z");
|
||||
|
||||
private final FakeClock fakeClock = new FakeClock(START_TIME);
|
||||
private final FakeClock fakeClock = new FakeClock(DateTime.parse("2000-01-01T00:00:00.0Z"));
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
final transient DatastoreEntityExtension datastore =
|
||||
new DatastoreEntityExtension().allThreads(true);
|
||||
|
||||
@RegisterExtension final transient InjectExtension injectExtension = new InjectExtension();
|
||||
|
||||
@RegisterExtension
|
||||
final transient JpaIntegrationTestExtension database =
|
||||
new JpaTestExtensions.Builder().withClock(fakeClock).buildIntegrationTestExtension();
|
||||
@@ -68,52 +52,25 @@ class RegistryJpaWriteTest implements Serializable {
|
||||
final transient TestPipelineExtension testPipeline =
|
||||
TestPipelineExtension.create().enableAbandonedNodeEnforcement(true);
|
||||
|
||||
private ImmutableList<Entity> contacts;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() throws Exception {
|
||||
try (BackupTestStore store = new BackupTestStore(fakeClock)) {
|
||||
injectExtension.setStaticField(Ofy.class, "clock", fakeClock);
|
||||
|
||||
// Required for contacts created below.
|
||||
Registrar ofyRegistrar = AppEngineExtension.makeRegistrar2();
|
||||
store.insertOrUpdate(ofyRegistrar);
|
||||
putInDb(store.loadAsOfyEntity(ofyRegistrar));
|
||||
|
||||
ImmutableList.Builder<Entity> builder = new ImmutableList.Builder<>();
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ContactResource contact = newContactResource("contact_" + i);
|
||||
store.insertOrUpdate(contact);
|
||||
builder.add(store.loadAsDatastoreEntity(contact));
|
||||
}
|
||||
contacts = builder.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void writeToSql_twoWriters() {
|
||||
jpaTm().transact(() -> jpaTm().put(AppEngineExtension.makeRegistrar2()));
|
||||
ImmutableList.Builder<ContactResource> contactsBuilder = new ImmutableList.Builder<>();
|
||||
for (int i = 0; i < 3; i++) {
|
||||
contactsBuilder.add(newContactResource("contact_" + i));
|
||||
}
|
||||
ImmutableList<ContactResource> contacts = contactsBuilder.build();
|
||||
testPipeline
|
||||
.apply(Create.of(contacts))
|
||||
.apply(
|
||||
Create.of(
|
||||
contacts.stream()
|
||||
.map(InitSqlTestUtils::entityToBytes)
|
||||
.map(bytes -> VersionedEntity.from(0L, bytes))
|
||||
.collect(Collectors.toList())))
|
||||
.apply(
|
||||
RegistryJpaIO.<VersionedEntity>write()
|
||||
RegistryJpaIO.<ContactResource>write()
|
||||
.withName("ContactResource")
|
||||
.withBatchSize(4)
|
||||
.withShards(2)
|
||||
.withJpaConverter(Transforms::convertVersionedEntityToSqlEntity));
|
||||
.withShards(2));
|
||||
testPipeline.run().waitUntilFinish();
|
||||
|
||||
assertThat(jpaTm().transact(() -> jpaTm().loadAllOf(ContactResource.class)))
|
||||
.comparingElementsUsing(immutableObjectCorrespondence("revisions", "updateTimestamp"))
|
||||
.containsExactlyElementsIn(
|
||||
contacts.stream()
|
||||
.map(InitSqlTestUtils::datastoreToOfyEntity)
|
||||
.map(ImmutableObject.class::cast)
|
||||
.collect(ImmutableList.toImmutableList()));
|
||||
.containsExactlyElementsIn(contacts);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
// Copyright 2020 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.beam.initsql;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.beam.initsql.BackupPaths.getCloudSQLCredentialFilePatterns;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link google.registry.beam.initsql.BackupPaths}. */
|
||||
public class BackupPathsTest {
|
||||
|
||||
@Test
|
||||
void getCloudSQLCredentialFilePatterns_alpha() {
|
||||
assertThat(getCloudSQLCredentialFilePatterns("alpha"))
|
||||
.containsExactly(
|
||||
"gs://domain-registry-dev-deploy/cloudsql-credentials/alpha/admin_credential.enc");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getCloudSQLCredentialFilePatterns_crash() {
|
||||
assertThat(getCloudSQLCredentialFilePatterns("crash"))
|
||||
.containsExactly(
|
||||
"gs://domain-registry-dev-deploy/cloudsql-credentials/crash/admin_credential.enc");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getCloudSQLCredentialFilePatterns_sandbox() {
|
||||
assertThat(getCloudSQLCredentialFilePatterns("sandbox"))
|
||||
.containsExactly(
|
||||
"gs://domain-registry-dev-deploy/cloudsql-credentials/sandbox/admin_credential.enc");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getCloudSQLCredentialFilePatterns_production() {
|
||||
assertThat(getCloudSQLCredentialFilePatterns("production"))
|
||||
.containsExactly(
|
||||
"gs://domain-registry-dev-deploy/cloudsql-credentials/production/admin_credential.enc");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getEnvFromProject_illegal() {
|
||||
assertThrows(IllegalArgumentException.class, () -> getCloudSQLCredentialFilePatterns("bad"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getEnvFromProject_null() {
|
||||
assertThrows(IllegalArgumentException.class, () -> getCloudSQLCredentialFilePatterns(null));
|
||||
}
|
||||
}
|
||||
@@ -1,204 +0,0 @@
|
||||
// Copyright 2020 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.beam.initsql;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static google.registry.model.ofy.ObjectifyService.auditedOfy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.ofyTm;
|
||||
|
||||
import com.google.appengine.api.datastore.DatastoreService;
|
||||
import com.google.appengine.api.datastore.DatastoreServiceFactory;
|
||||
import com.google.appengine.api.datastore.Entity;
|
||||
import com.google.appengine.api.datastore.EntityNotFoundException;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.backup.CommitLogExports;
|
||||
import google.registry.backup.VersionedEntity;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.ofy.CommitLogCheckpoint;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.tools.LevelDbFileBuilder;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
|
||||
/**
|
||||
* Wrapper of a Datastore test instance that can generate backups.
|
||||
*
|
||||
* <p>A Datastore backup consists of an unsynchronized data export and a sequence of incremental
|
||||
* Commit Logs that overlap with the export process. Together they can be used to recreate a
|
||||
* consistent snapshot of the Datastore.
|
||||
*
|
||||
* <p>For convenience of test-writing, the {@link #fakeClock} is advanced by 1 millisecond after
|
||||
* every transaction is invoked on this store, ensuring strictly increasing timestamps on causally
|
||||
* dependent transactions. In production, the same ordering is ensured by sleep and retry.
|
||||
*/
|
||||
public final class BackupTestStore implements AutoCloseable {
|
||||
|
||||
private static final DateTimeFormatter EXPORT_TIMESTAMP_FORMAT =
|
||||
DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss_SSS");
|
||||
|
||||
private final FakeClock fakeClock;
|
||||
private AppEngineExtension appEngine;
|
||||
/** For fetching the persisted Datastore Entity directly. */
|
||||
private DatastoreService datastoreService;
|
||||
|
||||
private CommitLogCheckpoint prevCommitLogCheckpoint;
|
||||
|
||||
public BackupTestStore(FakeClock fakeClock) throws Exception {
|
||||
this.fakeClock = fakeClock;
|
||||
this.appEngine =
|
||||
new AppEngineExtension.Builder()
|
||||
.withDatastoreAndCloudSql()
|
||||
.withoutCannedData()
|
||||
.withClock(fakeClock)
|
||||
.build();
|
||||
this.appEngine.setUp();
|
||||
datastoreService = DatastoreServiceFactory.getDatastoreService();
|
||||
}
|
||||
|
||||
/** Returns the timestamp of the transaction. */
|
||||
long transact(Iterable<Object> deletes, Iterable<Object> newOrUpdated) {
|
||||
long timestamp = fakeClock.nowUtc().getMillis();
|
||||
ofyTm()
|
||||
.transact(
|
||||
() -> {
|
||||
auditedOfy().delete().entities(deletes);
|
||||
auditedOfy().save().entities(newOrUpdated);
|
||||
});
|
||||
fakeClock.advanceOneMilli();
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts or updates {@code entities} in the Datastore and returns the timestamp of this
|
||||
* transaction.
|
||||
*/
|
||||
@SafeVarargs
|
||||
public final long insertOrUpdate(Object... entities) {
|
||||
long timestamp = fakeClock.nowUtc().getMillis();
|
||||
ofyTm().transact(() -> auditedOfy().save().entities(entities).now());
|
||||
fakeClock.advanceOneMilli();
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
/** Deletes {@code entities} from the Datastore and returns the timestamp of this transaction. */
|
||||
@SafeVarargs
|
||||
public final long delete(Object... entities) {
|
||||
long timestamp = fakeClock.nowUtc().getMillis();
|
||||
ofyTm().transact(() -> auditedOfy().delete().entities(entities).now());
|
||||
fakeClock.advanceOneMilli();
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the persisted data that corresponds to {@code ofyEntity} as a Datastore {@link Entity}.
|
||||
*
|
||||
* <p>A typical use case for this method is in a test, when the caller has persisted newly created
|
||||
* Objectify entity and want to find out the values of certain assign-on-persist properties. See
|
||||
* {@link VersionedEntity} for more information.
|
||||
*/
|
||||
public Entity loadAsDatastoreEntity(Object ofyEntity) {
|
||||
try {
|
||||
return datastoreService.get(Key.create(ofyEntity).getRaw());
|
||||
} catch (EntityNotFoundException e) {
|
||||
throw new NoSuchElementException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the persisted data that corresponds to {@code ofyEntity} as an Objectify entity.
|
||||
*
|
||||
* <p>See {@link #loadAsDatastoreEntity} and {@link VersionedEntity} for more information.
|
||||
*/
|
||||
public ImmutableObject loadAsOfyEntity(ImmutableObject ofyEntity) {
|
||||
try {
|
||||
return auditedOfy().load().fromEntity(datastoreService.get(Key.create(ofyEntity).getRaw()));
|
||||
} catch (EntityNotFoundException e) {
|
||||
throw new NoSuchElementException(e.getMessage());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Exports entities of the caller provided types and returns the directory where data is exported.
|
||||
*
|
||||
* @param exportRootPath path to the root directory of all exports. A subdirectory will be created
|
||||
* for this export
|
||||
* @param pojoTypes java class of all entities to be exported
|
||||
* @param excludes {@link Set} of {@link Key keys} of the entities not to export.This can be used
|
||||
* to simulate an inconsistent export
|
||||
* @return directory where data is exported
|
||||
*/
|
||||
File export(String exportRootPath, Iterable<Class<?>> pojoTypes, Set<Key<?>> excludes)
|
||||
throws IOException {
|
||||
File exportDirectory = getExportDirectory(exportRootPath);
|
||||
for (Class<?> pojoType : pojoTypes) {
|
||||
File perKindFile =
|
||||
new File(
|
||||
BackupPaths.getExportFileNameByShard(
|
||||
exportDirectory.getAbsolutePath(), Key.getKind(pojoType), 0));
|
||||
checkState(
|
||||
perKindFile.getParentFile().mkdirs(),
|
||||
"Failed to create per-kind export directory for %s.",
|
||||
perKindFile.getParentFile().getAbsolutePath());
|
||||
exportOneKind(perKindFile, pojoType, excludes);
|
||||
}
|
||||
return exportDirectory;
|
||||
}
|
||||
|
||||
private void exportOneKind(File perKindFile, Class<?> pojoType, Set<Key<?>> excludes)
|
||||
throws IOException {
|
||||
LevelDbFileBuilder builder = new LevelDbFileBuilder(perKindFile);
|
||||
for (Object pojo : auditedOfy().load().type(pojoType).iterable()) {
|
||||
if (!excludes.contains(Key.create(pojo))) {
|
||||
try {
|
||||
// Must preserve UpdateTimestamp. Do not use auditedOfy().save().toEntity(pojo)!
|
||||
builder.addEntity(datastoreService.get(Key.create(pojo).getRaw()));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
builder.build();
|
||||
}
|
||||
|
||||
File saveCommitLogs(String commitLogDir) {
|
||||
CommitLogCheckpoint checkpoint = CommitLogExports.computeCheckpoint(fakeClock);
|
||||
File commitLogFile =
|
||||
CommitLogExports.saveCommitLogs(commitLogDir, prevCommitLogCheckpoint, checkpoint);
|
||||
prevCommitLogCheckpoint = checkpoint;
|
||||
return commitLogFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
if (appEngine != null) {
|
||||
appEngine.tearDown();
|
||||
appEngine = null;
|
||||
}
|
||||
}
|
||||
|
||||
private File getExportDirectory(String exportRootPath) {
|
||||
File exportDirectory =
|
||||
new File(exportRootPath, fakeClock.nowUtc().toString(EXPORT_TIMESTAMP_FORMAT));
|
||||
checkState(
|
||||
exportDirectory.mkdirs(),
|
||||
"Failed to create export directory %s.",
|
||||
exportDirectory.getAbsolutePath());
|
||||
return exportDirectory;
|
||||
}
|
||||
}
|
||||
@@ -1,242 +0,0 @@
|
||||
// Copyright 2020 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.beam.initsql;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth.assertWithMessage;
|
||||
import static com.google.common.truth.Truth8.assertThat;
|
||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||
import static google.registry.testing.DatabaseHelper.newContactResource;
|
||||
import static google.registry.testing.DatabaseHelper.newDomainBase;
|
||||
import static google.registry.testing.DatabaseHelper.newRegistry;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.backup.CommitLogImports;
|
||||
import google.registry.backup.VersionedEntity;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.DesignatedContact;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.tools.LevelDbLogReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.stream.Stream;
|
||||
import org.apache.beam.sdk.values.KV;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
/** Unit tests for {@link BackupTestStore}. */
|
||||
public class BackupTestStoreTest {
|
||||
private static final DateTime START_TIME = DateTime.parse("2000-01-01T00:00:00.0Z");
|
||||
|
||||
@TempDir File tempDir;
|
||||
|
||||
@RegisterExtension
|
||||
final transient JpaIntegrationTestExtension jpaIntegrationTestExtension =
|
||||
new JpaTestExtensions.Builder().buildIntegrationTestExtension();
|
||||
|
||||
@RegisterExtension
|
||||
@Order(value = 1)
|
||||
final transient DatastoreEntityExtension datastoreEntityExtension =
|
||||
new DatastoreEntityExtension();
|
||||
|
||||
@RegisterExtension InjectExtension injectExtension = new InjectExtension();
|
||||
|
||||
private FakeClock fakeClock;
|
||||
private BackupTestStore store;
|
||||
|
||||
// Test data:
|
||||
private Registry registry;
|
||||
private ContactResource contact;
|
||||
private DomainBase domain;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() throws Exception {
|
||||
fakeClock = new FakeClock(START_TIME);
|
||||
store = new BackupTestStore(fakeClock);
|
||||
injectExtension.setStaticField(Ofy.class, "clock", fakeClock);
|
||||
|
||||
registry = newRegistry("tld1", "TLD1");
|
||||
store.insertOrUpdate(registry);
|
||||
|
||||
contact = newContactResource("contact_1");
|
||||
domain = newDomainBase("domain1.tld1", contact);
|
||||
store.insertOrUpdate(contact, domain);
|
||||
|
||||
// Save persisted data for assertions.
|
||||
registry = (Registry) store.loadAsOfyEntity(registry);
|
||||
contact = (ContactResource) store.loadAsOfyEntity(contact);
|
||||
domain = (DomainBase) store.loadAsOfyEntity(domain);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void afterEach() throws Exception {
|
||||
store.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void export_filesCreated() throws IOException {
|
||||
String exportRootPath = tempDir.getAbsolutePath();
|
||||
assertThat(fakeClock.nowUtc().toString()).isEqualTo("2000-01-01T00:00:00.002Z");
|
||||
File exportFolder = new File(exportRootPath, "2000-01-01T00:00:00_002");
|
||||
assertWithMessage("Directory %s should not exist.", exportFolder.getAbsoluteFile())
|
||||
.that(exportFolder.exists())
|
||||
.isFalse();
|
||||
File actualExportFolder = export(exportRootPath, ImmutableSet.of());
|
||||
assertThat(actualExportFolder).isEquivalentAccordingToCompareTo(exportFolder);
|
||||
try (Stream<String> files =
|
||||
Files.walk(exportFolder.toPath())
|
||||
.filter(Files::isRegularFile)
|
||||
.map(Path::toString)
|
||||
.map(string -> string.substring(exportFolder.getAbsolutePath().length()))) {
|
||||
assertThat(files)
|
||||
.containsExactly(
|
||||
"/all_namespaces/kind_Registry/output-0",
|
||||
"/all_namespaces/kind_DomainBase/output-0",
|
||||
"/all_namespaces/kind_ContactResource/output-0");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void export_folderNameChangesWithTime() throws IOException {
|
||||
String exportRootPath = tempDir.getAbsolutePath();
|
||||
fakeClock.advanceOneMilli();
|
||||
File exportFolder = new File(exportRootPath, "2000-01-01T00:00:00_003");
|
||||
assertWithMessage("Directory %s should not exist.", exportFolder.getAbsoluteFile())
|
||||
.that(exportFolder.exists())
|
||||
.isFalse();
|
||||
assertThat(export(exportRootPath, ImmutableSet.of()))
|
||||
.isEquivalentAccordingToCompareTo(exportFolder);
|
||||
}
|
||||
|
||||
@Test
|
||||
void export_dataReadBack() throws IOException {
|
||||
String exportRootPath = tempDir.getAbsolutePath();
|
||||
File exportFolder = export(exportRootPath, ImmutableSet.of());
|
||||
ImmutableList<Object> loadedRegistries =
|
||||
loadExportedEntities(new File(exportFolder, "/all_namespaces/kind_Registry/output-0"));
|
||||
assertThat(loadedRegistries).containsExactly(registry);
|
||||
|
||||
ImmutableList<Object> loadedDomains =
|
||||
loadExportedEntities(new File(exportFolder, "/all_namespaces/kind_DomainBase/output-0"));
|
||||
assertThat(loadedDomains).containsExactly(domain);
|
||||
|
||||
ImmutableList<Object> loadedContacts =
|
||||
loadExportedEntities(
|
||||
new File(exportFolder, "/all_namespaces/kind_ContactResource/output-0"));
|
||||
assertThat(loadedContacts).containsExactly(contact);
|
||||
}
|
||||
|
||||
@Test
|
||||
void export_excludeSomeEntity() throws IOException {
|
||||
Registry newRegistry = newRegistry("tld2", "TLD2");
|
||||
store.insertOrUpdate(newRegistry);
|
||||
newRegistry = (Registry) store.loadAsOfyEntity(newRegistry);
|
||||
|
||||
String exportRootPath = tempDir.getAbsolutePath();
|
||||
File exportFolder =
|
||||
export(
|
||||
exportRootPath, ImmutableSet.of(Key.create(getCrossTldKey(), Registry.class, "tld1")));
|
||||
ImmutableList<Object> loadedRegistries =
|
||||
loadExportedEntities(new File(exportFolder, "/all_namespaces/kind_Registry/output-0"));
|
||||
assertThat(loadedRegistries).containsExactly(newRegistry);
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveCommitLogs_fileCreated() {
|
||||
File commitLogFile = store.saveCommitLogs(tempDir.getAbsolutePath());
|
||||
assertThat(commitLogFile.exists()).isTrue();
|
||||
assertThat(commitLogFile.getName()).isEqualTo("commit_diff_until_2000-01-01T00:00:00.002Z");
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveCommitLogs_inserts() {
|
||||
File commitLogFile = store.saveCommitLogs(tempDir.getAbsolutePath());
|
||||
assertThat(commitLogFile.exists()).isTrue();
|
||||
ImmutableList<VersionedEntity> mutations = CommitLogImports.loadEntities(commitLogFile);
|
||||
InitSqlTestUtils.assertContainsExactlyElementsIn(
|
||||
mutations,
|
||||
KV.of(fakeClock.nowUtc().getMillis() - 2, store.loadAsDatastoreEntity(registry)),
|
||||
KV.of(fakeClock.nowUtc().getMillis() - 1, store.loadAsDatastoreEntity(contact)),
|
||||
KV.of(fakeClock.nowUtc().getMillis() - 1, store.loadAsDatastoreEntity(domain)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveCommitLogs_deletes() {
|
||||
fakeClock.advanceOneMilli();
|
||||
store.saveCommitLogs(tempDir.getAbsolutePath());
|
||||
ContactResource newContact = newContactResource("contact2");
|
||||
VKey<ContactResource> vKey = newContact.createVKey();
|
||||
domain =
|
||||
domain
|
||||
.asBuilder()
|
||||
.setRegistrant(vKey)
|
||||
.setContacts(
|
||||
ImmutableSet.of(
|
||||
DesignatedContact.create(DesignatedContact.Type.ADMIN, vKey),
|
||||
DesignatedContact.create(DesignatedContact.Type.TECH, vKey)))
|
||||
.build();
|
||||
store.insertOrUpdate(domain, newContact);
|
||||
store.delete(contact);
|
||||
File commitLogFile = store.saveCommitLogs(tempDir.getAbsolutePath());
|
||||
ImmutableList<VersionedEntity> mutations = CommitLogImports.loadEntities(commitLogFile);
|
||||
InitSqlTestUtils.assertContainsExactlyElementsIn(
|
||||
mutations,
|
||||
KV.of(fakeClock.nowUtc().getMillis() - 1, Key.create(contact).getRaw()),
|
||||
KV.of(fakeClock.nowUtc().getMillis() - 2, store.loadAsDatastoreEntity(domain)),
|
||||
KV.of(fakeClock.nowUtc().getMillis() - 2, store.loadAsDatastoreEntity(newContact)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveCommitLogs_empty() {
|
||||
fakeClock.advanceOneMilli();
|
||||
store.saveCommitLogs(tempDir.getAbsolutePath());
|
||||
fakeClock.advanceOneMilli();
|
||||
File commitLogFile = store.saveCommitLogs(tempDir.getAbsolutePath());
|
||||
assertThat(commitLogFile.exists()).isTrue();
|
||||
assertThat(CommitLogImports.loadEntities(commitLogFile)).isEmpty();
|
||||
}
|
||||
|
||||
private File export(String exportRootPath, ImmutableSet<Key<?>> excludes) throws IOException {
|
||||
return store.export(
|
||||
exportRootPath,
|
||||
ImmutableList.of(ContactResource.class, DomainBase.class, Registry.class),
|
||||
excludes);
|
||||
}
|
||||
|
||||
private static ImmutableList<Object> loadExportedEntities(File dataFile) throws IOException {
|
||||
return Streams.stream(LevelDbLogReader.from(dataFile.toPath()))
|
||||
.map(InitSqlTestUtils::bytesToEntity)
|
||||
.map(InitSqlTestUtils::datastoreToOfyEntity)
|
||||
.collect(ImmutableList.toImmutableList());
|
||||
}
|
||||
}
|
||||
@@ -1,245 +0,0 @@
|
||||
// Copyright 2020 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.beam.initsql;
|
||||
|
||||
import static google.registry.testing.DatabaseHelper.newContactResource;
|
||||
import static google.registry.testing.DatabaseHelper.newDomainBase;
|
||||
import static google.registry.testing.DatabaseHelper.newRegistry;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.backup.VersionedEntity;
|
||||
import google.registry.beam.TestPipelineExtension;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import org.apache.beam.sdk.coders.StringUtf8Coder;
|
||||
import org.apache.beam.sdk.io.fs.MatchResult.Metadata;
|
||||
import org.apache.beam.sdk.testing.PAssert;
|
||||
import org.apache.beam.sdk.transforms.Create;
|
||||
import org.apache.beam.sdk.transforms.DoFn;
|
||||
import org.apache.beam.sdk.transforms.ParDo;
|
||||
import org.apache.beam.sdk.values.KV;
|
||||
import org.apache.beam.sdk.values.PCollection;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
/** Unit tests for {@link Transforms} related to loading CommitLogs. */
|
||||
class CommitLogTransformsTest implements Serializable {
|
||||
|
||||
private static final DateTime START_TIME = DateTime.parse("2000-01-01T00:00:00.0Z");
|
||||
private final FakeClock fakeClock = new FakeClock(START_TIME);
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@TempDir
|
||||
transient Path tmpDir;
|
||||
|
||||
@RegisterExtension final transient InjectExtension injectExtension = new InjectExtension();
|
||||
|
||||
@RegisterExtension
|
||||
final transient JpaIntegrationTestExtension jpaIntegrationTestExtension =
|
||||
new JpaTestExtensions.Builder().withClock(fakeClock).buildIntegrationTestExtension();
|
||||
|
||||
@RegisterExtension
|
||||
@Order(value = 1)
|
||||
final transient DatastoreEntityExtension datastoreEntityExtension =
|
||||
new DatastoreEntityExtension().allThreads(true);
|
||||
|
||||
@RegisterExtension
|
||||
final transient TestPipelineExtension testPipeline =
|
||||
TestPipelineExtension.create().enableAbandonedNodeEnforcement(true);
|
||||
|
||||
private transient BackupTestStore store;
|
||||
private File commitLogsDir;
|
||||
private File firstCommitLogFile;
|
||||
|
||||
// Canned data:
|
||||
private transient Registry registry;
|
||||
private transient ContactResource contact;
|
||||
private transient DomainBase domain;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() throws Exception {
|
||||
store = new BackupTestStore(fakeClock);
|
||||
injectExtension.setStaticField(Ofy.class, "clock", fakeClock);
|
||||
|
||||
registry = newRegistry("tld1", "TLD1");
|
||||
store.insertOrUpdate(registry);
|
||||
contact = newContactResource("contact_1");
|
||||
domain = newDomainBase("domain1.tld1", contact);
|
||||
store.insertOrUpdate(contact, domain);
|
||||
|
||||
// Save persisted data for assertions.
|
||||
registry = (Registry) store.loadAsOfyEntity(registry);
|
||||
contact = (ContactResource) store.loadAsOfyEntity(contact);
|
||||
domain = (DomainBase) store.loadAsOfyEntity(domain);
|
||||
|
||||
commitLogsDir = Files.createDirectory(tmpDir.resolve("commit_logs")).toFile();
|
||||
firstCommitLogFile = store.saveCommitLogs(commitLogsDir.getAbsolutePath());
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void afterEach() throws Exception {
|
||||
if (store != null) {
|
||||
store.close();
|
||||
store = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void getCommitLogFilePatterns() {
|
||||
PCollection<String> patterns =
|
||||
testPipeline.apply(
|
||||
"Get CommitLog file patterns",
|
||||
Transforms.getCommitLogFilePatterns(commitLogsDir.getAbsolutePath()));
|
||||
|
||||
ImmutableList<String> expectedPatterns =
|
||||
ImmutableList.of(commitLogsDir.getAbsolutePath() + "/commit_diff_until_*");
|
||||
|
||||
PAssert.that(patterns).containsInAnyOrder(expectedPatterns);
|
||||
|
||||
testPipeline.run();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFilesByPatterns() {
|
||||
PCollection<Metadata> fileMetas =
|
||||
testPipeline
|
||||
.apply(
|
||||
"File patterns to metadata",
|
||||
Create.of(commitLogsDir.getAbsolutePath() + "/commit_diff_until_*")
|
||||
.withCoder(StringUtf8Coder.of()))
|
||||
.apply(Transforms.getFilesByPatterns());
|
||||
|
||||
// Transform fileMetas to file names for assertions.
|
||||
PCollection<String> fileNames =
|
||||
fileMetas.apply(
|
||||
"File metadata to path string",
|
||||
ParDo.of(
|
||||
new DoFn<Metadata, String>() {
|
||||
@ProcessElement
|
||||
public void processElement(
|
||||
@Element Metadata metadata, OutputReceiver<String> out) {
|
||||
out.output(metadata.resourceId().toString());
|
||||
}
|
||||
}));
|
||||
|
||||
ImmutableList<String> expectedFilenames =
|
||||
ImmutableList.of(firstCommitLogFile.getAbsolutePath());
|
||||
|
||||
PAssert.that(fileNames).containsInAnyOrder(expectedFilenames);
|
||||
|
||||
testPipeline.run();
|
||||
}
|
||||
|
||||
@Test
|
||||
void filterCommitLogsByTime() throws IOException {
|
||||
ImmutableList<String> commitLogFilenames =
|
||||
ImmutableList.of(
|
||||
"commit_diff_until_2000-01-01T00:00:00.000Z",
|
||||
"commit_diff_until_2000-01-01T00:00:00.001Z",
|
||||
"commit_diff_until_2000-01-01T00:00:00.002Z",
|
||||
"commit_diff_until_2000-01-01T00:00:00.003Z",
|
||||
"commit_diff_until_2000-01-01T00:00:00.004Z");
|
||||
|
||||
for (String name : commitLogFilenames) {
|
||||
new File(commitLogsDir, name).createNewFile();
|
||||
}
|
||||
|
||||
PCollection<String> filteredFilenames =
|
||||
testPipeline
|
||||
.apply(
|
||||
"Get commitlog file patterns",
|
||||
Transforms.getCommitLogFilePatterns(commitLogsDir.getAbsolutePath()))
|
||||
.apply("Find commitlog files", Transforms.getFilesByPatterns())
|
||||
.apply(
|
||||
"Filtered by Time",
|
||||
Transforms.filterCommitLogsByTime(
|
||||
DateTime.parse("2000-01-01T00:00:00.001Z"),
|
||||
DateTime.parse("2000-01-01T00:00:00.003Z")))
|
||||
.apply(
|
||||
"Extract path strings",
|
||||
ParDo.of(
|
||||
new DoFn<Metadata, String>() {
|
||||
@ProcessElement
|
||||
public void processElement(
|
||||
@Element Metadata fileMeta, OutputReceiver<String> out) {
|
||||
out.output(fileMeta.resourceId().getFilename());
|
||||
}
|
||||
}));
|
||||
PAssert.that(filteredFilenames)
|
||||
.containsInAnyOrder(
|
||||
"commit_diff_until_2000-01-01T00:00:00.001Z",
|
||||
"commit_diff_until_2000-01-01T00:00:00.002Z");
|
||||
|
||||
testPipeline.run();
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadOneCommitLogFile() {
|
||||
PCollection<VersionedEntity> entities =
|
||||
testPipeline
|
||||
.apply(
|
||||
"Get CommitLog file patterns",
|
||||
Transforms.getCommitLogFilePatterns(commitLogsDir.getAbsolutePath()))
|
||||
.apply("Find CommitLogs", Transforms.getFilesByPatterns())
|
||||
.apply(
|
||||
Transforms.loadCommitLogsFromFiles(
|
||||
ImmutableSet.of("Registry", "ContactResource", "DomainBase")));
|
||||
|
||||
InitSqlTestUtils.assertContainsExactlyElementsIn(
|
||||
entities,
|
||||
KV.of(fakeClock.nowUtc().getMillis() - 2, store.loadAsDatastoreEntity(registry)),
|
||||
KV.of(fakeClock.nowUtc().getMillis() - 1, store.loadAsDatastoreEntity(contact)),
|
||||
KV.of(fakeClock.nowUtc().getMillis() - 1, store.loadAsDatastoreEntity(domain)));
|
||||
|
||||
testPipeline.run();
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadOneCommitLogFile_filterByKind() {
|
||||
PCollection<VersionedEntity> entities =
|
||||
testPipeline
|
||||
.apply(
|
||||
"Get CommitLog file patterns",
|
||||
Transforms.getCommitLogFilePatterns(commitLogsDir.getAbsolutePath()))
|
||||
.apply("Find CommitLogs", Transforms.getFilesByPatterns())
|
||||
.apply(
|
||||
Transforms.loadCommitLogsFromFiles(ImmutableSet.of("Registry", "ContactResource")));
|
||||
|
||||
InitSqlTestUtils.assertContainsExactlyElementsIn(
|
||||
entities,
|
||||
KV.of(fakeClock.nowUtc().getMillis() - 2, store.loadAsDatastoreEntity(registry)),
|
||||
KV.of(fakeClock.nowUtc().getMillis() - 1, store.loadAsDatastoreEntity(contact)));
|
||||
|
||||
testPipeline.run();
|
||||
}
|
||||
}
|
||||
@@ -1,295 +0,0 @@
|
||||
// Copyright 2021 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.beam.initsql;
|
||||
|
||||
import static google.registry.model.common.Cursor.CursorType.BRDA;
|
||||
import static google.registry.model.common.Cursor.CursorType.RECURRING_BILLING;
|
||||
import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE;
|
||||
import static google.registry.testing.DatabaseHelper.newRegistry;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static google.registry.testing.DatabaseHelper.persistSimpleResource;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.flows.domain.DomainFlowUtils;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.billing.BillingEvent.Flag;
|
||||
import google.registry.model.billing.BillingEvent.Reason;
|
||||
import google.registry.model.common.Cursor;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.DesignatedContact;
|
||||
import google.registry.model.domain.DomainAuthInfo;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.GracePeriod;
|
||||
import google.registry.model.domain.launch.LaunchNotice;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
import google.registry.model.domain.secdns.DelegationSignerData;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarContact;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.model.transfer.DomainTransferData;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import org.joda.money.Money;
|
||||
|
||||
/**
|
||||
* Sets up a test scenario in Datastore.
|
||||
*
|
||||
* <p>The {@link #initializeData} populates Datastore with test data, including {@link DomainBase},
|
||||
* {@link DomainHistory}, and commit logs. The up-to-date version of the relevant entities are saved
|
||||
* in public instance variables (e.g., {@link #domain} for easy access.
|
||||
*/
|
||||
public class DatastoreSetupHelper {
|
||||
|
||||
/**
|
||||
* All kinds of entities to be set up in the Datastore. Must contain all kinds known to {@link
|
||||
* InitSqlPipeline}.
|
||||
*/
|
||||
public static final ImmutableList<Class<?>> ALL_KINDS =
|
||||
ImmutableList.of(
|
||||
Registry.class,
|
||||
Cursor.class,
|
||||
Registrar.class,
|
||||
ContactResource.class,
|
||||
RegistrarContact.class,
|
||||
DomainBase.class,
|
||||
HostResource.class,
|
||||
HistoryEntry.class,
|
||||
AllocationToken.class,
|
||||
BillingEvent.Recurring.class,
|
||||
BillingEvent.OneTime.class,
|
||||
BillingEvent.Cancellation.class,
|
||||
PollMessage.class);
|
||||
|
||||
private final Path tmpDir;
|
||||
private final FakeClock fakeClock;
|
||||
|
||||
public File exportRootDir;
|
||||
public File exportDir;
|
||||
public File commitLogDir;
|
||||
|
||||
public Registrar registrar1;
|
||||
public Registrar registrar2;
|
||||
public DomainBase domain;
|
||||
public ContactResource contact1;
|
||||
public ContactResource contact2;
|
||||
public HostResource hostResource;
|
||||
|
||||
public DomainHistory historyEntry;
|
||||
|
||||
public Cursor globalCursor;
|
||||
public Cursor tldCursor;
|
||||
|
||||
public DatastoreSetupHelper(Path tempDir, FakeClock fakeClock) {
|
||||
this.tmpDir = tempDir;
|
||||
this.fakeClock = fakeClock;
|
||||
}
|
||||
|
||||
public DatastoreSetupHelper initializeData() throws Exception {
|
||||
try (BackupTestStore store = new BackupTestStore(fakeClock)) {
|
||||
exportRootDir = Files.createDirectory(tmpDir.resolve("exports")).toFile();
|
||||
|
||||
persistResource(newRegistry("com", "COM"));
|
||||
registrar1 = persistResource(AppEngineExtension.makeRegistrar1());
|
||||
registrar2 = persistResource(AppEngineExtension.makeRegistrar2());
|
||||
Key<DomainBase> domainKey = Key.create(null, DomainBase.class, "4-COM");
|
||||
hostResource =
|
||||
persistResource(
|
||||
new HostResource.Builder()
|
||||
.setHostName("ns1.example.com")
|
||||
.setSuperordinateDomain(VKey.from(domainKey))
|
||||
.setRepoId("1-COM")
|
||||
.setCreationRegistrarId(registrar1.getRegistrarId())
|
||||
.setPersistedCurrentSponsorRegistrarId(registrar2.getRegistrarId())
|
||||
.build());
|
||||
contact1 =
|
||||
persistResource(
|
||||
new ContactResource.Builder()
|
||||
.setContactId("contact_id1")
|
||||
.setRepoId("2-COM")
|
||||
.setCreationRegistrarId(registrar1.getRegistrarId())
|
||||
.setPersistedCurrentSponsorRegistrarId(registrar2.getRegistrarId())
|
||||
.build());
|
||||
contact2 =
|
||||
persistResource(
|
||||
new ContactResource.Builder()
|
||||
.setContactId("contact_id2")
|
||||
.setRepoId("3-COM")
|
||||
.setCreationRegistrarId(registrar1.getRegistrarId())
|
||||
.setPersistedCurrentSponsorRegistrarId(registrar1.getRegistrarId())
|
||||
.build());
|
||||
persistSimpleResource(
|
||||
new RegistrarContact.Builder()
|
||||
.setParent(registrar1)
|
||||
.setName("John Abused")
|
||||
.setEmailAddress("johnabuse@example.com")
|
||||
.setVisibleInWhoisAsAdmin(true)
|
||||
.setVisibleInWhoisAsTech(false)
|
||||
.setPhoneNumber("+1.2125551213")
|
||||
.setFaxNumber("+1.2125551213")
|
||||
.setTypes(ImmutableSet.of(RegistrarContact.Type.ABUSE, RegistrarContact.Type.ADMIN))
|
||||
.build());
|
||||
historyEntry =
|
||||
persistResource(
|
||||
new DomainHistory.Builder()
|
||||
.setDomainRepoId(domainKey.getName())
|
||||
.setModificationTime(fakeClock.nowUtc())
|
||||
.setRegistrarId(registrar1.getRegistrarId())
|
||||
.setType(HistoryEntry.Type.DOMAIN_CREATE)
|
||||
.build());
|
||||
persistResource(
|
||||
new AllocationToken.Builder().setToken("abc123").setTokenType(SINGLE_USE).build());
|
||||
Key<DomainHistory> historyEntryKey = Key.create(historyEntry);
|
||||
BillingEvent.OneTime onetimeBillEvent =
|
||||
new BillingEvent.OneTime.Builder()
|
||||
.setId(1)
|
||||
.setReason(Reason.RENEW)
|
||||
.setTargetId("example.com")
|
||||
.setRegistrarId("TheRegistrar")
|
||||
.setCost(Money.parse("USD 44.00"))
|
||||
.setPeriodYears(4)
|
||||
.setEventTime(fakeClock.nowUtc())
|
||||
.setBillingTime(fakeClock.nowUtc())
|
||||
.setParent(historyEntryKey)
|
||||
.build();
|
||||
persistResource(onetimeBillEvent);
|
||||
Key<BillingEvent.OneTime> oneTimeBillKey = Key.create(onetimeBillEvent);
|
||||
BillingEvent.Recurring recurringBillEvent =
|
||||
new BillingEvent.Recurring.Builder()
|
||||
.setId(2)
|
||||
.setReason(Reason.RENEW)
|
||||
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
|
||||
.setTargetId("example.com")
|
||||
.setRegistrarId("TheRegistrar")
|
||||
.setEventTime(fakeClock.nowUtc())
|
||||
.setRecurrenceEndTime(END_OF_TIME)
|
||||
.setParent(historyEntryKey)
|
||||
.build();
|
||||
persistResource(recurringBillEvent);
|
||||
VKey<BillingEvent.Recurring> recurringBillKey = recurringBillEvent.createVKey();
|
||||
PollMessage.Autorenew autorenewPollMessage =
|
||||
new PollMessage.Autorenew.Builder()
|
||||
.setId(3L)
|
||||
.setTargetId("example.com")
|
||||
.setRegistrarId("TheRegistrar")
|
||||
.setEventTime(fakeClock.nowUtc())
|
||||
.setMsg("Domain was auto-renewed.")
|
||||
.setParent(historyEntry)
|
||||
.build();
|
||||
persistResource(autorenewPollMessage);
|
||||
VKey<PollMessage.Autorenew> autorenewPollKey = autorenewPollMessage.createVKey();
|
||||
PollMessage.OneTime oneTimePollMessage =
|
||||
new PollMessage.OneTime.Builder()
|
||||
.setId(1L)
|
||||
.setParent(historyEntry)
|
||||
.setEventTime(fakeClock.nowUtc())
|
||||
.setRegistrarId("TheRegistrar")
|
||||
.setMsg(DomainFlowUtils.COLLISION_MESSAGE)
|
||||
.build();
|
||||
persistResource(oneTimePollMessage);
|
||||
VKey<PollMessage.OneTime> onetimePollKey = oneTimePollMessage.createVKey();
|
||||
domain =
|
||||
persistResource(
|
||||
new DomainBase.Builder()
|
||||
.setDomainName("example.com")
|
||||
.setRepoId("4-COM")
|
||||
.setCreationRegistrarId(registrar1.getRegistrarId())
|
||||
.setLastEppUpdateTime(fakeClock.nowUtc())
|
||||
.setLastEppUpdateRegistrarId(registrar2.getRegistrarId())
|
||||
.setLastTransferTime(fakeClock.nowUtc())
|
||||
.setStatusValues(
|
||||
ImmutableSet.of(
|
||||
StatusValue.CLIENT_DELETE_PROHIBITED,
|
||||
StatusValue.SERVER_DELETE_PROHIBITED,
|
||||
StatusValue.SERVER_TRANSFER_PROHIBITED,
|
||||
StatusValue.SERVER_UPDATE_PROHIBITED,
|
||||
StatusValue.SERVER_RENEW_PROHIBITED,
|
||||
StatusValue.SERVER_HOLD))
|
||||
.setRegistrant(contact1.createVKey())
|
||||
.setContacts(
|
||||
ImmutableSet.of(
|
||||
DesignatedContact.create(
|
||||
DesignatedContact.Type.ADMIN, contact2.createVKey())))
|
||||
.setNameservers(ImmutableSet.of(hostResource.createVKey()))
|
||||
.setSubordinateHosts(ImmutableSet.of("ns1.example.com"))
|
||||
.setPersistedCurrentSponsorRegistrarId(registrar2.getRegistrarId())
|
||||
.setRegistrationExpirationTime(fakeClock.nowUtc().plusYears(1))
|
||||
.setAuthInfo(DomainAuthInfo.create(PasswordAuth.create("password")))
|
||||
.setDsData(
|
||||
ImmutableSet.of(DelegationSignerData.create(1, 2, 3, new byte[] {0, 1, 2})))
|
||||
.setLaunchNotice(
|
||||
LaunchNotice.create("tcnid", "validatorId", START_OF_TIME, START_OF_TIME))
|
||||
.setTransferData(
|
||||
new DomainTransferData.Builder()
|
||||
.setGainingRegistrarId(registrar1.getRegistrarId())
|
||||
.setLosingRegistrarId(registrar2.getRegistrarId())
|
||||
.setPendingTransferExpirationTime(fakeClock.nowUtc())
|
||||
.setServerApproveEntities(
|
||||
ImmutableSet.of(
|
||||
VKey.from(oneTimeBillKey), recurringBillKey, autorenewPollKey))
|
||||
.setServerApproveBillingEvent(VKey.from(oneTimeBillKey))
|
||||
.setServerApproveAutorenewEvent(recurringBillKey)
|
||||
.setServerApproveAutorenewPollMessage(autorenewPollKey)
|
||||
.setTransferRequestTime(fakeClock.nowUtc().plusDays(1))
|
||||
.setTransferStatus(TransferStatus.SERVER_APPROVED)
|
||||
.setTransferRequestTrid(Trid.create("client-trid", "server-trid"))
|
||||
.build())
|
||||
.setDeletePollMessage(onetimePollKey)
|
||||
.setAutorenewBillingEvent(recurringBillKey)
|
||||
.setAutorenewPollMessage(autorenewPollKey)
|
||||
.setSmdId("smdid")
|
||||
.addGracePeriod(
|
||||
GracePeriod.create(
|
||||
GracePeriodStatus.ADD,
|
||||
"4-COM",
|
||||
fakeClock.nowUtc().plusDays(1),
|
||||
"TheRegistrar",
|
||||
null))
|
||||
.build());
|
||||
persistResource(
|
||||
new BillingEvent.Cancellation.Builder()
|
||||
.setReason(Reason.RENEW)
|
||||
.setTargetId(domain.getDomainName())
|
||||
.setRegistrarId(domain.getCurrentSponsorRegistrarId())
|
||||
.setEventTime(fakeClock.nowUtc())
|
||||
.setBillingTime(fakeClock.nowUtc())
|
||||
.setRecurringEventKey(recurringBillEvent.createVKey())
|
||||
.setParent(historyEntryKey)
|
||||
.build());
|
||||
globalCursor = persistResource(Cursor.createGlobal(RECURRING_BILLING, fakeClock.nowUtc()));
|
||||
tldCursor = persistResource(Cursor.create(BRDA, fakeClock.nowUtc(), Registry.get("com")));
|
||||
exportDir = store.export(exportRootDir.getAbsolutePath(), ALL_KINDS, ImmutableSet.of());
|
||||
commitLogDir = Files.createDirectory(tmpDir.resolve("commits")).toFile();
|
||||
fakeClock.advanceOneMilli();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,233 +0,0 @@
|
||||
// Copyright 2020 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.beam.initsql;
|
||||
|
||||
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
|
||||
import static google.registry.model.ofy.ObjectifyService.auditedOfy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.testing.DatabaseHelper.cloneAndSetAutoTimestamps;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.google.appengine.api.datastore.Entity;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.billing.BillingEvent.OneTime;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.DesignatedContact;
|
||||
import google.registry.model.domain.DomainAuthInfo;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.GracePeriod;
|
||||
import google.registry.model.domain.launch.LaunchNotice;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
import google.registry.model.domain.secdns.DelegationSignerData;
|
||||
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.transfer.DomainTransferData;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import org.joda.time.Instant;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link DomainBaseUtil}. */
|
||||
public class DomainBaseUtilTest {
|
||||
|
||||
private final FakeClock fakeClock = new FakeClock(Instant.now());
|
||||
|
||||
private DomainBase domain;
|
||||
private Entity domainEntity;
|
||||
private Key<OneTime> oneTimeBillKey;
|
||||
private VKey<BillingEvent.Recurring> recurringBillKey;
|
||||
private Key<DomainBase> domainKey;
|
||||
|
||||
@RegisterExtension
|
||||
AppEngineExtension appEngineExtension =
|
||||
AppEngineExtension.builder().withDatastoreAndCloudSql().withClock(fakeClock).build();
|
||||
|
||||
@RegisterExtension InjectExtension injectExtension = new InjectExtension();
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
injectExtension.setStaticField(Ofy.class, "clock", fakeClock);
|
||||
createTld("com");
|
||||
domainKey = Key.create(null, DomainBase.class, "4-COM");
|
||||
VKey<HostResource> hostKey =
|
||||
persistResource(
|
||||
new HostResource.Builder()
|
||||
.setHostName("ns1.example.com")
|
||||
.setSuperordinateDomain(VKey.from(domainKey))
|
||||
.setRepoId("1-COM")
|
||||
.build())
|
||||
.createVKey();
|
||||
VKey<ContactResource> contact1Key =
|
||||
persistResource(
|
||||
new ContactResource.Builder()
|
||||
.setContactId("contact_id1")
|
||||
.setRepoId("2-COM")
|
||||
.build())
|
||||
.createVKey();
|
||||
VKey<ContactResource> contact2Key =
|
||||
persistResource(
|
||||
new ContactResource.Builder()
|
||||
.setContactId("contact_id2")
|
||||
.setRepoId("3-COM")
|
||||
.build())
|
||||
.createVKey();
|
||||
Key<HistoryEntry> historyEntryKey =
|
||||
Key.create(
|
||||
persistResource(
|
||||
new DomainHistory.Builder()
|
||||
.setDomainRepoId(domainKey.getName())
|
||||
.setType(HistoryEntry.Type.DOMAIN_CREATE)
|
||||
.setRegistrarId("TheRegistrar")
|
||||
.setModificationTime(fakeClock.nowUtc().minusYears(1))
|
||||
.build()));
|
||||
oneTimeBillKey = Key.create(historyEntryKey, BillingEvent.OneTime.class, 1);
|
||||
recurringBillKey = VKey.from(Key.create(historyEntryKey, BillingEvent.Recurring.class, 2));
|
||||
VKey<PollMessage.Autorenew> autorenewPollKey =
|
||||
VKey.from(Key.create(historyEntryKey, PollMessage.Autorenew.class, 3));
|
||||
VKey<PollMessage.OneTime> onetimePollKey =
|
||||
VKey.from(Key.create(historyEntryKey, PollMessage.OneTime.class, 1));
|
||||
// Set up a new persisted domain entity.
|
||||
domain =
|
||||
persistResource(
|
||||
cloneAndSetAutoTimestamps(
|
||||
new DomainBase.Builder()
|
||||
.setDomainName("example.com")
|
||||
.setRepoId("4-COM")
|
||||
.setCreationRegistrarId("a registrar")
|
||||
.setLastEppUpdateTime(fakeClock.nowUtc())
|
||||
.setLastEppUpdateRegistrarId("AnotherRegistrar")
|
||||
.setLastTransferTime(fakeClock.nowUtc())
|
||||
.setStatusValues(
|
||||
ImmutableSet.of(
|
||||
StatusValue.CLIENT_DELETE_PROHIBITED,
|
||||
StatusValue.SERVER_DELETE_PROHIBITED,
|
||||
StatusValue.SERVER_TRANSFER_PROHIBITED,
|
||||
StatusValue.SERVER_UPDATE_PROHIBITED,
|
||||
StatusValue.SERVER_RENEW_PROHIBITED,
|
||||
StatusValue.SERVER_HOLD))
|
||||
.setRegistrant(contact1Key)
|
||||
.setContacts(
|
||||
ImmutableSet.of(
|
||||
DesignatedContact.create(DesignatedContact.Type.ADMIN, contact2Key)))
|
||||
.setNameservers(ImmutableSet.of(hostKey))
|
||||
.setSubordinateHosts(ImmutableSet.of("ns1.example.com"))
|
||||
.setPersistedCurrentSponsorRegistrarId("losing")
|
||||
.setRegistrationExpirationTime(fakeClock.nowUtc().plusYears(1))
|
||||
.setAuthInfo(DomainAuthInfo.create(PasswordAuth.create("password")))
|
||||
.setDsData(
|
||||
ImmutableSet.of(DelegationSignerData.create(1, 2, 3, new byte[] {0, 1, 2})))
|
||||
.setLaunchNotice(
|
||||
LaunchNotice.create("tcnid", "validatorId", START_OF_TIME, START_OF_TIME))
|
||||
.setTransferData(
|
||||
new DomainTransferData.Builder()
|
||||
.setGainingRegistrarId("gaining")
|
||||
.setLosingRegistrarId("losing")
|
||||
.setPendingTransferExpirationTime(fakeClock.nowUtc())
|
||||
.setServerApproveEntities(
|
||||
ImmutableSet.of(
|
||||
VKey.from(oneTimeBillKey), recurringBillKey, autorenewPollKey))
|
||||
.setServerApproveBillingEvent(VKey.from(oneTimeBillKey))
|
||||
.setServerApproveAutorenewEvent(recurringBillKey)
|
||||
.setServerApproveAutorenewPollMessage(autorenewPollKey)
|
||||
.setTransferRequestTime(fakeClock.nowUtc().plusDays(1))
|
||||
.setTransferStatus(TransferStatus.SERVER_APPROVED)
|
||||
.setTransferRequestTrid(Trid.create("client-trid", "server-trid"))
|
||||
.build())
|
||||
.setDeletePollMessage(onetimePollKey)
|
||||
.setAutorenewBillingEvent(recurringBillKey)
|
||||
.setAutorenewPollMessage(autorenewPollKey)
|
||||
.setSmdId("smdid")
|
||||
.addGracePeriod(
|
||||
GracePeriod.create(
|
||||
GracePeriodStatus.ADD,
|
||||
"4-COM",
|
||||
fakeClock.nowUtc().plusDays(1),
|
||||
"registrar",
|
||||
null))
|
||||
.build()));
|
||||
domainEntity = tm().transact(() -> auditedOfy().toEntity(domain));
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeBillingAndPollAndHosts_allFkeysPresent() {
|
||||
DomainBase domainTransformedByOfy =
|
||||
domain
|
||||
.asBuilder()
|
||||
.setAutorenewBillingEvent(null)
|
||||
.setAutorenewPollMessage(null)
|
||||
.setNameservers(ImmutableSet.of())
|
||||
.setDeletePollMessage(null)
|
||||
.setTransferData(null)
|
||||
.setGracePeriods(ImmutableSet.of())
|
||||
.build();
|
||||
DomainBase domainTransformedByUtil =
|
||||
(DomainBase) auditedOfy().toPojo(DomainBaseUtil.removeBillingAndPollAndHosts(domainEntity));
|
||||
// Compensates for the missing INACTIVE status.
|
||||
domainTransformedByUtil = domainTransformedByUtil.asBuilder().build();
|
||||
assertAboutImmutableObjects()
|
||||
.that(domainTransformedByUtil)
|
||||
.isEqualExceptFields(domainTransformedByOfy, "revisions", "updateTimestamp");
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeBillingAndPollAndHosts_noFkeysPresent() {
|
||||
DomainBase domainWithoutFKeys =
|
||||
domain
|
||||
.asBuilder()
|
||||
.setAutorenewBillingEvent(null)
|
||||
.setAutorenewPollMessage(null)
|
||||
.setNameservers(ImmutableSet.of())
|
||||
.setDeletePollMessage(null)
|
||||
.setTransferData(null)
|
||||
.setGracePeriods(ImmutableSet.of())
|
||||
.build();
|
||||
Entity entityWithoutFkeys = tm().transact(() -> auditedOfy().toEntity(domainWithoutFKeys));
|
||||
DomainBase domainTransformedByUtil =
|
||||
(DomainBase)
|
||||
auditedOfy().toPojo(DomainBaseUtil.removeBillingAndPollAndHosts(entityWithoutFkeys));
|
||||
// Compensates for the missing INACTIVE status.
|
||||
domainTransformedByUtil = domainTransformedByUtil.asBuilder().build();
|
||||
assertAboutImmutableObjects()
|
||||
.that(domainTransformedByUtil)
|
||||
.isEqualExceptFields(domainWithoutFKeys, "revisions", "updateTimestamp");
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeBillingAndPollAndHosts_notDomainBase() {
|
||||
Entity contactEntity =
|
||||
tm().transact(() -> auditedOfy().toEntity(DatabaseHelper.newContactResource("contact")));
|
||||
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> DomainBaseUtil.removeBillingAndPollAndHosts(contactEntity));
|
||||
}
|
||||
}
|
||||
@@ -1,201 +0,0 @@
|
||||
// Copyright 2020 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.beam.initsql;
|
||||
|
||||
import static google.registry.testing.DatabaseHelper.newContactResource;
|
||||
import static google.registry.testing.DatabaseHelper.newDomainBase;
|
||||
import static google.registry.testing.DatabaseHelper.newRegistry;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.backup.VersionedEntity;
|
||||
import google.registry.beam.TestPipelineExtension;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import java.io.File;
|
||||
import java.io.Serializable;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import org.apache.beam.sdk.coders.StringUtf8Coder;
|
||||
import org.apache.beam.sdk.io.fs.MatchResult.Metadata;
|
||||
import org.apache.beam.sdk.testing.PAssert;
|
||||
import org.apache.beam.sdk.transforms.Create;
|
||||
import org.apache.beam.sdk.transforms.DoFn;
|
||||
import org.apache.beam.sdk.transforms.ParDo;
|
||||
import org.apache.beam.sdk.values.KV;
|
||||
import org.apache.beam.sdk.values.PCollection;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link Transforms} related to loading Datastore exports.
|
||||
*
|
||||
* <p>This class implements {@link Serializable} so that test {@link DoFn} classes may be inlined.
|
||||
*/
|
||||
class ExportLoadingTransformsTest implements Serializable {
|
||||
|
||||
private static final DateTime START_TIME = DateTime.parse("2000-01-01T00:00:00.0Z");
|
||||
|
||||
private static final ImmutableList<Class<?>> ALL_KINDS =
|
||||
ImmutableList.of(Registry.class, ContactResource.class, DomainBase.class);
|
||||
private static final ImmutableSet<String> ALL_KIND_STRS =
|
||||
ALL_KINDS.stream().map(Key::getKind).collect(ImmutableSet.toImmutableSet());
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@TempDir
|
||||
transient Path tmpDir;
|
||||
|
||||
@RegisterExtension final transient InjectExtension injectExtension = new InjectExtension();
|
||||
|
||||
@RegisterExtension
|
||||
final transient JpaIntegrationTestExtension jpaIntegrationTestExtension =
|
||||
new JpaTestExtensions.Builder().buildIntegrationTestExtension();
|
||||
|
||||
@RegisterExtension
|
||||
@Order(value = 1)
|
||||
final transient DatastoreEntityExtension datastoreEntityExtension =
|
||||
new DatastoreEntityExtension().allThreads(true);
|
||||
|
||||
@RegisterExtension
|
||||
final transient TestPipelineExtension testPipeline =
|
||||
TestPipelineExtension.create().enableAbandonedNodeEnforcement(true);
|
||||
|
||||
private FakeClock fakeClock;
|
||||
private transient BackupTestStore store;
|
||||
private File exportDir;
|
||||
|
||||
// Canned data:
|
||||
private transient Registry registry;
|
||||
private transient ContactResource contact;
|
||||
private transient DomainBase domain;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() throws Exception {
|
||||
fakeClock = new FakeClock(START_TIME);
|
||||
store = new BackupTestStore(fakeClock);
|
||||
injectExtension.setStaticField(Ofy.class, "clock", fakeClock);
|
||||
|
||||
registry = newRegistry("tld1", "TLD1");
|
||||
store.insertOrUpdate(registry);
|
||||
|
||||
contact = newContactResource("contact_1");
|
||||
domain = newDomainBase("domain1.tld1", contact);
|
||||
store.insertOrUpdate(contact, domain);
|
||||
|
||||
// Save persisted data for assertions.
|
||||
registry = (Registry) store.loadAsOfyEntity(registry);
|
||||
contact = (ContactResource) store.loadAsOfyEntity(contact);
|
||||
domain = (DomainBase) store.loadAsOfyEntity(domain);
|
||||
|
||||
exportDir = store.export(tmpDir.toAbsolutePath().toString(), ALL_KINDS, Collections.EMPTY_SET);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void afterEach() throws Exception {
|
||||
if (store != null) {
|
||||
store.close();
|
||||
store = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void getExportFilePatterns() {
|
||||
PCollection<String> patterns =
|
||||
testPipeline.apply(
|
||||
"Get Datastore file patterns",
|
||||
Transforms.getDatastoreExportFilePatterns(exportDir.getAbsolutePath(), ALL_KIND_STRS));
|
||||
|
||||
ImmutableList<String> expectedPatterns =
|
||||
ImmutableList.of(
|
||||
exportDir.getAbsolutePath() + "/all_namespaces/kind_Registry/output-*",
|
||||
exportDir.getAbsolutePath() + "/all_namespaces/kind_DomainBase/output-*",
|
||||
exportDir.getAbsolutePath() + "/all_namespaces/kind_ContactResource/output-*");
|
||||
|
||||
PAssert.that(patterns).containsInAnyOrder(expectedPatterns);
|
||||
|
||||
testPipeline.run();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFilesByPatterns() {
|
||||
PCollection<Metadata> fileMetas =
|
||||
testPipeline
|
||||
.apply(
|
||||
"File patterns to metadata",
|
||||
Create.of(
|
||||
exportDir.getAbsolutePath() + "/all_namespaces/kind_Registry/output-*",
|
||||
exportDir.getAbsolutePath() + "/all_namespaces/kind_DomainBase/output-*",
|
||||
exportDir.getAbsolutePath()
|
||||
+ "/all_namespaces/kind_ContactResource/output-*")
|
||||
.withCoder(StringUtf8Coder.of()))
|
||||
.apply(Transforms.getFilesByPatterns());
|
||||
|
||||
// Transform fileMetas to file names for assertions.
|
||||
PCollection<String> fileNames =
|
||||
fileMetas.apply(
|
||||
"File metadata to path string",
|
||||
ParDo.of(
|
||||
new DoFn<Metadata, String>() {
|
||||
@ProcessElement
|
||||
public void processElement(
|
||||
@Element Metadata metadata, OutputReceiver<String> out) {
|
||||
out.output(metadata.resourceId().toString());
|
||||
}
|
||||
}));
|
||||
|
||||
ImmutableList<String> expectedFilenames =
|
||||
ImmutableList.of(
|
||||
exportDir.getAbsolutePath() + "/all_namespaces/kind_Registry/output-0",
|
||||
exportDir.getAbsolutePath() + "/all_namespaces/kind_DomainBase/output-0",
|
||||
exportDir.getAbsolutePath() + "/all_namespaces/kind_ContactResource/output-0");
|
||||
|
||||
PAssert.that(fileNames).containsInAnyOrder(expectedFilenames);
|
||||
|
||||
testPipeline.run();
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadDataFromFiles() {
|
||||
PCollection<VersionedEntity> entities =
|
||||
testPipeline
|
||||
.apply(
|
||||
"Get Datastore file patterns",
|
||||
Transforms.getDatastoreExportFilePatterns(
|
||||
exportDir.getAbsolutePath(), ALL_KIND_STRS))
|
||||
.apply("Find Datastore files", Transforms.getFilesByPatterns())
|
||||
.apply("Load from Datastore files", Transforms.loadExportDataFromFiles());
|
||||
|
||||
InitSqlTestUtils.assertContainsExactlyElementsIn(
|
||||
entities,
|
||||
KV.of(Transforms.EXPORT_ENTITY_TIME_STAMP, store.loadAsDatastoreEntity(registry)),
|
||||
KV.of(Transforms.EXPORT_ENTITY_TIME_STAMP, store.loadAsDatastoreEntity(contact)),
|
||||
KV.of(Transforms.EXPORT_ENTITY_TIME_STAMP, store.loadAsDatastoreEntity(domain)));
|
||||
|
||||
testPipeline.run();
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
// Copyright 2020 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.beam.initsql;
|
||||
|
||||
import static google.registry.testing.truth.TextDiffSubject.assertWithMessageAboutUrlSource;
|
||||
|
||||
import com.google.common.io.Resources;
|
||||
import google.registry.beam.TestPipelineExtension;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.net.URL;
|
||||
import org.apache.beam.runners.core.construction.renderer.PipelineDotRenderer;
|
||||
import org.apache.beam.sdk.options.PipelineOptionsFactory;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Manages visualization of {@link InitSqlPipeline}. */
|
||||
class InitSqlPipelineGraphTest {
|
||||
|
||||
private static final String GOLDEN_DOT_FILE = "pipeline_golden.dot";
|
||||
|
||||
private static final String[] OPTIONS_ARGS =
|
||||
new String[] {
|
||||
"--commitLogStartTimestamp=2000-01-01TZ",
|
||||
"--commitLogEndTimestamp=2000-01-02TZ",
|
||||
"--datastoreExportDir=/somedir",
|
||||
"--commitLogDir=/someotherdir",
|
||||
"--registryEnvironment=ALPHA"
|
||||
};
|
||||
|
||||
private static final transient InitSqlPipelineOptions options =
|
||||
PipelineOptionsFactory.fromArgs(OPTIONS_ARGS)
|
||||
.withValidation()
|
||||
.as(InitSqlPipelineOptions.class);
|
||||
|
||||
@RegisterExtension
|
||||
final transient TestPipelineExtension testPipeline =
|
||||
TestPipelineExtension.create().enableAbandonedNodeEnforcement(false);
|
||||
|
||||
@Test
|
||||
void createPipeline_compareGraph() throws IOException {
|
||||
new InitSqlPipeline(options).setupPipeline(testPipeline);
|
||||
String dotString = PipelineDotRenderer.toDotString(testPipeline);
|
||||
URL goldenDotUrl = Resources.getResource(InitSqlPipelineGraphTest.class, GOLDEN_DOT_FILE);
|
||||
File outputFile = new File(new File(goldenDotUrl.getFile()).getParent(), "pipeline_curr.dot");
|
||||
try (PrintStream ps = new PrintStream(outputFile)) {
|
||||
ps.print(dotString);
|
||||
}
|
||||
assertWithMessageAboutUrlSource(
|
||||
"InitSqlPipeline graph changed. Run :core:updateInitSqlPipelineGraph to update.")
|
||||
.that(outputFile.toURI().toURL())
|
||||
.hasSameContentAs(goldenDotUrl);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
// Copyright 2020 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.beam.initsql;
|
||||
|
||||
import org.apache.beam.sdk.options.PipelineOptionsFactory;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link google.registry.beam.initsql.InitSqlPipelineOptions}. * */
|
||||
public class InitSqlPipelineOptionsTest {
|
||||
|
||||
@Test
|
||||
void registerToValidate() {
|
||||
PipelineOptionsFactory.register(InitSqlPipelineOptions.class);
|
||||
}
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
// Copyright 2020 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.beam.initsql;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
|
||||
import static google.registry.model.ImmutableObjectSubject.immutableObjectCorrespondence;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
|
||||
import google.registry.beam.TestPipelineExtension;
|
||||
import google.registry.model.common.Cursor;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import java.nio.file.Path;
|
||||
import org.apache.beam.sdk.options.PipelineOptionsFactory;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
/** Unit tests for {@link InitSqlPipeline}. */
|
||||
class InitSqlPipelineTest {
|
||||
private static final DateTime START_TIME = DateTime.parse("2000-01-01T00:00:00.0Z");
|
||||
|
||||
private FakeClock fakeClock = new FakeClock(START_TIME);
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
final transient DatastoreEntityExtension datastore =
|
||||
new DatastoreEntityExtension().allThreads(true);
|
||||
|
||||
@RegisterExtension final transient InjectExtension injectExtension = new InjectExtension();
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@TempDir
|
||||
transient Path tmpDir;
|
||||
|
||||
@RegisterExtension
|
||||
final transient TestPipelineExtension testPipeline =
|
||||
TestPipelineExtension.create().enableAbandonedNodeEnforcement(true);
|
||||
|
||||
@RegisterExtension
|
||||
final transient JpaIntegrationTestExtension database =
|
||||
new JpaTestExtensions.Builder().withClock(fakeClock).buildIntegrationTestExtension();
|
||||
|
||||
DatastoreSetupHelper setupHelper;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() throws Exception {
|
||||
injectExtension.setStaticField(Ofy.class, "clock", fakeClock);
|
||||
setupHelper = new DatastoreSetupHelper(tmpDir, fakeClock).initializeData();
|
||||
}
|
||||
|
||||
@Test
|
||||
void runPipeline() {
|
||||
InitSqlPipelineOptions options =
|
||||
PipelineOptionsFactory.fromArgs(
|
||||
"--commitLogStartTimestamp=" + START_TIME,
|
||||
"--commitLogEndTimestamp=" + fakeClock.nowUtc().plusMillis(1),
|
||||
"--datastoreExportDir=" + setupHelper.exportDir.getAbsolutePath(),
|
||||
"--commitLogDir=" + setupHelper.commitLogDir.getAbsolutePath())
|
||||
.withValidation()
|
||||
.as(InitSqlPipelineOptions.class);
|
||||
InitSqlPipeline initSqlPipeline = new InitSqlPipeline(options);
|
||||
initSqlPipeline.run(testPipeline).waitUntilFinish();
|
||||
assertHostResourceEquals(
|
||||
jpaTm().transact(() -> jpaTm().loadByKey(setupHelper.hostResource.createVKey())),
|
||||
setupHelper.hostResource);
|
||||
assertThat(jpaTm().transact(() -> jpaTm().loadAllOf(Registrar.class)))
|
||||
.comparingElementsUsing(immutableObjectCorrespondence("lastUpdateTime"))
|
||||
.containsExactly(setupHelper.registrar1, setupHelper.registrar2);
|
||||
assertThat(jpaTm().transact(() -> jpaTm().loadAllOf(ContactResource.class)))
|
||||
.comparingElementsUsing(immutableObjectCorrespondence("revisions", "updateTimestamp"))
|
||||
.containsExactly(setupHelper.contact1, setupHelper.contact2);
|
||||
assertDomainEquals(
|
||||
jpaTm().transact(() -> jpaTm().loadByKey(setupHelper.domain.createVKey())),
|
||||
setupHelper.domain);
|
||||
assertThat(jpaTm().transact(() -> jpaTm().loadAllOf(Cursor.class)))
|
||||
.comparingElementsUsing(immutableObjectCorrespondence())
|
||||
.containsExactly(setupHelper.globalCursor, setupHelper.tldCursor);
|
||||
}
|
||||
|
||||
private static void assertHostResourceEquals(HostResource actual, HostResource expected) {
|
||||
assertAboutImmutableObjects()
|
||||
.that(actual)
|
||||
.isEqualExceptFields(expected, "superordinateDomain", "revisions", "updateTimestamp");
|
||||
assertThat(actual.getSuperordinateDomain().getSqlKey())
|
||||
.isEqualTo(expected.getSuperordinateDomain().getSqlKey());
|
||||
}
|
||||
|
||||
private static void assertDomainEquals(DomainBase actual, DomainBase expected) {
|
||||
assertAboutImmutableObjects()
|
||||
.that(actual)
|
||||
.isEqualExceptFields(
|
||||
expected,
|
||||
"revisions",
|
||||
"updateTimestamp",
|
||||
"autorenewPollMessage",
|
||||
"deletePollMessage",
|
||||
"nsHosts",
|
||||
"gracePeriods",
|
||||
"transferData");
|
||||
assertThat(actual.getAdminContact().getSqlKey())
|
||||
.isEqualTo(expected.getAdminContact().getSqlKey());
|
||||
assertThat(actual.getRegistrant().getSqlKey()).isEqualTo(expected.getRegistrant().getSqlKey());
|
||||
assertThat(actual.getNsHosts()).isEqualTo(expected.getNsHosts());
|
||||
assertThat(actual.getAutorenewPollMessage().getOfyKey())
|
||||
.isEqualTo(expected.getAutorenewPollMessage().getOfyKey());
|
||||
assertThat(actual.getDeletePollMessage().getOfyKey())
|
||||
.isEqualTo(expected.getDeletePollMessage().getOfyKey());
|
||||
assertThat(actual.getUpdateTimestamp()).isEqualTo(expected.getUpdateTimestamp());
|
||||
// TODO(weiminyu): check gracePeriods and transferData when it is easier to do
|
||||
}
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
// Copyright 2020 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.beam.initsql;
|
||||
|
||||
import static com.google.common.truth.Truth8.assertThat;
|
||||
import static google.registry.model.ofy.ObjectifyService.auditedOfy;
|
||||
import static org.apache.beam.sdk.values.TypeDescriptors.kvs;
|
||||
import static org.apache.beam.sdk.values.TypeDescriptors.strings;
|
||||
|
||||
import com.google.appengine.api.datastore.Entity;
|
||||
import com.google.appengine.api.datastore.EntityTranslator;
|
||||
import com.google.appengine.api.datastore.Key;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.common.truth.Truth;
|
||||
import com.google.storage.onestore.v3.OnestoreEntity.EntityProto;
|
||||
import google.registry.backup.VersionedEntity;
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Stream;
|
||||
import org.apache.beam.sdk.testing.PAssert;
|
||||
import org.apache.beam.sdk.transforms.DoFn;
|
||||
import org.apache.beam.sdk.transforms.GroupByKey;
|
||||
import org.apache.beam.sdk.transforms.MapElements;
|
||||
import org.apache.beam.sdk.transforms.ParDo;
|
||||
import org.apache.beam.sdk.values.KV;
|
||||
import org.apache.beam.sdk.values.PCollection;
|
||||
import org.apache.beam.sdk.values.TypeDescriptor;
|
||||
|
||||
/** Test helpers for populating SQL with Datastore backups. */
|
||||
public final class InitSqlTestUtils {
|
||||
|
||||
// Generates unique ids to distinguish reused transforms.
|
||||
private static final AtomicInteger TRANSFORM_ID_GEN = new AtomicInteger(0);
|
||||
|
||||
/** Converts a Datastore {@link Entity} to an Objectify entity. */
|
||||
public static Object datastoreToOfyEntity(Entity entity) {
|
||||
return auditedOfy().load().fromEntity(entity);
|
||||
}
|
||||
|
||||
/** Serializes a Datastore {@link Entity} to byte array. */
|
||||
public static byte[] entityToBytes(Entity entity) {
|
||||
return EntityTranslator.convertToPb(entity).toByteArray();
|
||||
}
|
||||
|
||||
/** Deserializes raw bytes into {@link Entity}. */
|
||||
public static Entity bytesToEntity(byte[] bytes) {
|
||||
EntityProto proto = new EntityProto();
|
||||
proto.parseFrom(bytes);
|
||||
return EntityTranslator.createFromPb(proto);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the {@code actual} {@link Collection} of {@link VersionedEntity VersionedEntities}
|
||||
* contains exactly the same elements in the {@code expected} array.
|
||||
*
|
||||
* <p>Each {@code expected} {@link KV key-value pair} refers to a versioned state of an Ofy
|
||||
* entity. The {@link KV#getKey key} is the timestamp, while the {@link KV#getValue value} is
|
||||
* either a Datastore {@link Entity} (for an existing entity) or a Datastore {@link Key} (for a
|
||||
* deleted entity).
|
||||
*
|
||||
* <p>The {@Entity} instances in both actual and expected data are converted to Objectify entities
|
||||
* so that value-equality checks can be performed. Datastore {@link Entity#equals Entity's equals
|
||||
* method} only checks key-equality.
|
||||
*/
|
||||
@SafeVarargs
|
||||
public static void assertContainsExactlyElementsIn(
|
||||
Collection<VersionedEntity> actual, KV<Long, Serializable>... expected) {
|
||||
assertThat(actual.stream().map(InitSqlTestUtils::rawEntityToOfyWithTimestamp))
|
||||
.containsExactlyElementsIn(
|
||||
Stream.of(expected)
|
||||
.map(InitSqlTestUtils::expectedToOfyWithTimestamp)
|
||||
.collect(ImmutableList.toImmutableList()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the {@code actual} {@link PCollection} of {@link VersionedEntity
|
||||
* VersionedEntities} contains exactly the same elements in the {@code expected} array.
|
||||
*
|
||||
* <p>This method makes assertions in the pipeline and only use {@link PAssert} on the result.
|
||||
* This way it supports assertions on Objectify entities, which {@code PAssert} cannot do ( since
|
||||
* we have not implemented Coders for them). Compared with PAssert-compatible options like {@code
|
||||
* google.registry.tools.EntityWrapper} or {@link EntityProto}, Objectify entities in Java give
|
||||
* better-formatted error messages when assertions fail.
|
||||
*
|
||||
* <p>Each {@code expected} {@link KV key-value pair} refers to a versioned state of an Ofy
|
||||
* entity. The {@link KV#getKey key} is the timestamp, while the {@link KV#getValue value} is
|
||||
* either a Datastore {@link Entity} (for an existing entity) or a Datastore {@link Key} (for a
|
||||
* deleted entity).
|
||||
*
|
||||
* <p>The {@Entity} instances in both actual and expected data are converted to Objectify entities
|
||||
* so that value-equality checks can be performed. Datastore {@link Entity#equals Entity's equals
|
||||
* method} only checks key-equality.
|
||||
*/
|
||||
@SafeVarargs
|
||||
public static void assertContainsExactlyElementsIn(
|
||||
PCollection<VersionedEntity> actual, KV<Long, Serializable>... expected) {
|
||||
PCollection<String> errMsgs =
|
||||
actual
|
||||
.apply(
|
||||
"MapElements_" + TRANSFORM_ID_GEN.getAndIncrement(),
|
||||
MapElements.into(kvs(strings(), TypeDescriptor.of(VersionedEntity.class)))
|
||||
.via(rawEntity -> KV.of("The One Key", rawEntity)))
|
||||
.apply("GroupByKey_" + TRANSFORM_ID_GEN.getAndIncrement(), GroupByKey.create())
|
||||
.apply(
|
||||
"assertContainsExactlyElementsIn_" + TRANSFORM_ID_GEN.getAndIncrement(),
|
||||
ParDo.of(
|
||||
new DoFn<KV<String, Iterable<VersionedEntity>>, String>() {
|
||||
@ProcessElement
|
||||
public void processElement(
|
||||
@Element KV<String, Iterable<VersionedEntity>> input,
|
||||
OutputReceiver<String> out) {
|
||||
ImmutableList<KV<Long, Object>> actual =
|
||||
Streams.stream(input.getValue())
|
||||
.map(InitSqlTestUtils::rawEntityToOfyWithTimestamp)
|
||||
.collect(ImmutableList.toImmutableList());
|
||||
try {
|
||||
Truth.assertThat(actual)
|
||||
.containsExactlyElementsIn(
|
||||
Stream.of(expected)
|
||||
.map(InitSqlTestUtils::expectedToOfyWithTimestamp)
|
||||
.collect(ImmutableList.toImmutableList()));
|
||||
} catch (AssertionError e) {
|
||||
out.output(e.toString());
|
||||
}
|
||||
}
|
||||
}));
|
||||
PAssert.that(errMsgs).empty();
|
||||
}
|
||||
|
||||
private static KV<Long, Object> rawEntityToOfyWithTimestamp(VersionedEntity rawEntity) {
|
||||
return KV.of(
|
||||
rawEntity.commitTimeMills(),
|
||||
rawEntity.getEntity().map(InitSqlTestUtils::datastoreToOfyEntity).orElse(rawEntity.key()));
|
||||
}
|
||||
|
||||
private static KV<Long, Object> expectedToOfyWithTimestamp(KV<Long, Serializable> kv) {
|
||||
return KV.of(
|
||||
kv.getKey(),
|
||||
kv.getValue() instanceof Key
|
||||
? kv.getValue()
|
||||
: datastoreToOfyEntity((Entity) kv.getValue()));
|
||||
}
|
||||
}
|
||||
@@ -1,190 +0,0 @@
|
||||
// Copyright 2020 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.beam.initsql;
|
||||
|
||||
import static google.registry.testing.DatabaseHelper.newContactResource;
|
||||
import static google.registry.testing.DatabaseHelper.newDomainBase;
|
||||
import static google.registry.testing.DatabaseHelper.newRegistry;
|
||||
|
||||
import com.google.appengine.api.datastore.Entity;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.beam.TestPipelineExtension;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.DomainAuthInfo;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import org.apache.beam.sdk.values.KV;
|
||||
import org.apache.beam.sdk.values.PCollectionTuple;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
/**
|
||||
* Unit test for {@link Transforms#loadDatastoreSnapshot}.
|
||||
*
|
||||
* <p>The test setup involves three entities, one Registry, one Domain, and two Contacts. Events
|
||||
* happen in the following order:
|
||||
*
|
||||
* <ol>
|
||||
* <li>Registry and a filler Contact are inserted to Datastore.
|
||||
* <li>A CommitLog is persisted.
|
||||
* <li>Registry is updated.
|
||||
* <li>Another Contact and Domain are inserted into Datastore.
|
||||
* <li>Datastore is exported, but misses the newly inserted Contact.
|
||||
* <li>Filler Contact is deleted.
|
||||
* <li>A second CommitLog is persisted.
|
||||
* <li>Domain is updated in the Datastore.
|
||||
* <li>The third and last CommitLog is persisted.
|
||||
* </ol>
|
||||
*
|
||||
* The final snapshot includes Registry, Domain, and Contact. This scenario verifies that:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Incremental changes committed before an export does not override the exported valie.
|
||||
* <li>Entity missed by an export can be recovered from later CommitLogs.
|
||||
* <li>Multiple changes to an entity is applied in order.
|
||||
* <li>Deletes are properly handled.
|
||||
* </ul>
|
||||
*/
|
||||
class LoadDatastoreSnapshotTest {
|
||||
|
||||
private static final DateTime START_TIME = DateTime.parse("2000-01-01T00:00:00.0Z");
|
||||
|
||||
private static final ImmutableList<Class<?>> ALL_KINDS =
|
||||
ImmutableList.of(Registry.class, ContactResource.class, DomainBase.class);
|
||||
private static final ImmutableSet<String> ALL_KIND_STRS =
|
||||
ALL_KINDS.stream().map(Key::getKind).collect(ImmutableSet.toImmutableSet());
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@TempDir
|
||||
transient Path tmpDir;
|
||||
|
||||
@RegisterExtension final transient InjectExtension injectExtension = new InjectExtension();
|
||||
|
||||
@RegisterExtension
|
||||
final transient JpaIntegrationTestExtension jpaIntegrationTestExtension =
|
||||
new JpaTestExtensions.Builder().buildIntegrationTestExtension();
|
||||
|
||||
@RegisterExtension
|
||||
@Order(value = 1)
|
||||
final transient DatastoreEntityExtension datastoreEntityExtension =
|
||||
new DatastoreEntityExtension().allThreads(true);
|
||||
|
||||
@RegisterExtension
|
||||
final transient TestPipelineExtension testPipeline =
|
||||
TestPipelineExtension.create().enableAbandonedNodeEnforcement(true);
|
||||
|
||||
private FakeClock fakeClock;
|
||||
private File exportRootDir;
|
||||
private File exportDir;
|
||||
private File commitLogsDir;
|
||||
|
||||
// Canned data:
|
||||
private transient Entity dsRegistry;
|
||||
private transient Entity dsContact;
|
||||
private transient Entity dsDomain;
|
||||
|
||||
private transient DateTime registryLastUpdateTime;
|
||||
private transient DateTime contactLastUpdateTime;
|
||||
private transient DateTime domainLastUpdateTime;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() throws Exception {
|
||||
fakeClock = new FakeClock(START_TIME);
|
||||
try (BackupTestStore store = new BackupTestStore(fakeClock)) {
|
||||
injectExtension.setStaticField(Ofy.class, "clock", fakeClock);
|
||||
|
||||
exportRootDir = Files.createDirectory(tmpDir.resolve("export_root")).toFile();
|
||||
commitLogsDir = Files.createDirectory(tmpDir.resolve("commit_logs")).toFile();
|
||||
|
||||
Registry registry = newRegistry("tld1", "TLD1");
|
||||
ContactResource fillerContact = newContactResource("contact_filler");
|
||||
store.insertOrUpdate(registry, fillerContact);
|
||||
store.saveCommitLogs(commitLogsDir.getAbsolutePath());
|
||||
|
||||
registry =
|
||||
registry
|
||||
.asBuilder()
|
||||
.setCreateBillingCost(registry.getStandardCreateCost().plus(1.0d))
|
||||
.build();
|
||||
registryLastUpdateTime = fakeClock.nowUtc();
|
||||
store.insertOrUpdate(registry);
|
||||
|
||||
ContactResource contact = newContactResource("contact");
|
||||
DomainBase domain = newDomainBase("domain1.tld1", contact);
|
||||
contactLastUpdateTime = fakeClock.nowUtc();
|
||||
store.insertOrUpdate(contact, domain);
|
||||
exportDir =
|
||||
store.export(
|
||||
exportRootDir.getAbsolutePath(), ALL_KINDS, ImmutableSet.of(Key.create(contact)));
|
||||
|
||||
store.delete(fillerContact);
|
||||
store.saveCommitLogs(commitLogsDir.getAbsolutePath());
|
||||
|
||||
domain =
|
||||
domain
|
||||
.asBuilder()
|
||||
.setAuthInfo(DomainAuthInfo.create(PasswordAuth.create("NewPass")))
|
||||
.build();
|
||||
domainLastUpdateTime = fakeClock.nowUtc();
|
||||
store.insertOrUpdate(domain);
|
||||
store.saveCommitLogs(commitLogsDir.getAbsolutePath());
|
||||
|
||||
fakeClock.advanceOneMilli();
|
||||
|
||||
// Save persisted data for assertions.
|
||||
dsRegistry = store.loadAsDatastoreEntity(registry);
|
||||
dsContact = store.loadAsDatastoreEntity(contact);
|
||||
dsDomain = store.loadAsDatastoreEntity(domain);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadDatastoreSnapshot() {
|
||||
PCollectionTuple snapshot =
|
||||
testPipeline.apply(
|
||||
Transforms.loadDatastoreSnapshot(
|
||||
exportDir.getAbsolutePath(),
|
||||
commitLogsDir.getAbsolutePath(),
|
||||
START_TIME,
|
||||
fakeClock.nowUtc(),
|
||||
ALL_KIND_STRS));
|
||||
InitSqlTestUtils.assertContainsExactlyElementsIn(
|
||||
snapshot.get(Transforms.createTagForKind("DomainBase")),
|
||||
KV.of(domainLastUpdateTime.getMillis(), dsDomain));
|
||||
InitSqlTestUtils.assertContainsExactlyElementsIn(
|
||||
snapshot.get(Transforms.createTagForKind("Registry")),
|
||||
KV.of(registryLastUpdateTime.getMillis(), dsRegistry));
|
||||
InitSqlTestUtils.assertContainsExactlyElementsIn(
|
||||
snapshot.get(Transforms.createTagForKind("ContactResource")),
|
||||
KV.of(contactLastUpdateTime.getMillis(), dsContact));
|
||||
testPipeline.run();
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
// Copyright 2021 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.beam.initsql;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.beam.initsql.Transforms.repairBadData;
|
||||
import static google.registry.model.ofy.ObjectifyService.auditedOfy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.ofyTm;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.newDomainBase;
|
||||
import static google.registry.testing.DatabaseHelper.newHostResource;
|
||||
|
||||
import com.google.appengine.api.datastore.Entity;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link Transforms}. */
|
||||
public class TransformsTest {
|
||||
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withDatastoreAndCloudSql().build();
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
createTld("tld");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRepairBadData_canonicalizesDomainName() {
|
||||
DomainBase domain = newDomainBase("foobar.tld");
|
||||
Entity entity = ofyTm().transact(() -> auditedOfy().toEntity(domain));
|
||||
entity.setIndexedProperty("fullyQualifiedDomainName", "FOOBäR.TLD");
|
||||
assertThat(((DomainBase) auditedOfy().toPojo(repairBadData(entity))).getDomainName())
|
||||
.isEqualTo("xn--foobr-jra.tld");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRepairBadData_canonicalizesHostName() {
|
||||
HostResource host = newHostResource("baz.foobar.tld");
|
||||
Entity entity = ofyTm().transact(() -> auditedOfy().toEntity(host));
|
||||
entity.setIndexedProperty(
|
||||
"fullyQualifiedHostName", "b̴̹͔͓̣̭̫͇͕̻̬̱͇͗͌́̆̋͒a̶̬̖͚̋̈́̽̇͝͠z̵͠.FOOBäR.TLD");
|
||||
assertThat(((HostResource) auditedOfy().toPojo(repairBadData(entity))).getHostName())
|
||||
.isEqualTo(
|
||||
"xn--baz-kdcb2ajgzb4jtg6doej4e6b9am7c7b6c5nd4k7gpa2a9a7dufyewec.xn--foobr-jra.tld");
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,6 @@ import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationT
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.TestDataHelper;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import google.registry.util.ResourceUtils;
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
@@ -95,10 +94,6 @@ class InvoicingPipelineTest {
|
||||
final JpaIntegrationTestExtension database =
|
||||
new JpaTestExtensions.Builder().withClock(new FakeClock()).buildIntegrationTestExtension();
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT + 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withJpa();
|
||||
|
||||
@TempDir Path tmpDir;
|
||||
|
||||
private static final String BILLING_BUCKET_URL = "billing_bucket";
|
||||
@@ -282,7 +277,6 @@ class InvoicingPipelineTest {
|
||||
@Test
|
||||
void testSuccess_fullSqlPipeline() throws Exception {
|
||||
setupCloudSql();
|
||||
options.setDatabase("CLOUD_SQL");
|
||||
InvoicingPipeline invoicingPipeline = new InvoicingPipeline(options);
|
||||
invoicingPipeline.setupPipeline(pipeline);
|
||||
pipeline.run(options).waitUntilFinish();
|
||||
|
||||
@@ -87,7 +87,6 @@ import google.registry.testing.CloudTasksHelper.TaskMatcher;
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeKeyringModule;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import java.io.IOException;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
@@ -166,10 +165,6 @@ public class RdePipelineTest {
|
||||
final JpaIntegrationTestExtension database =
|
||||
new JpaTestExtensions.Builder().withClock(clock).buildIntegrationTestExtension();
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT + 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withJpa();
|
||||
|
||||
@RegisterExtension
|
||||
final TestPipelineExtension pipeline =
|
||||
TestPipelineExtension.fromOptions(options).enableAbandonedNodeEnforcement(true);
|
||||
|
||||
@@ -42,7 +42,6 @@ import google.registry.persistence.transaction.JpaTransactionManager;
|
||||
import google.registry.persistence.transaction.TransactionManagerFactory;
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import org.apache.beam.sdk.options.PipelineOptionsFactory;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
@@ -70,10 +69,6 @@ public class ResaveAllEppResourcesPipelineTest {
|
||||
final JpaIntegrationTestExtension database =
|
||||
new JpaTestExtensions.Builder().withClock(fakeClock).buildIntegrationTestExtension();
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT + 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withJpa();
|
||||
|
||||
private final ResaveAllEppResourcesPipelineOptions options =
|
||||
PipelineOptionsFactory.create().as(ResaveAllEppResourcesPipelineOptions.class);
|
||||
|
||||
|
||||
@@ -50,7 +50,6 @@ import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationT
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeSleeper;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import google.registry.util.ResourceUtils;
|
||||
import google.registry.util.Retrier;
|
||||
import java.io.File;
|
||||
@@ -128,10 +127,6 @@ class Spec11PipelineTest {
|
||||
final JpaIntegrationTestExtension database =
|
||||
new JpaTestExtensions.Builder().withClock(new FakeClock()).buildIntegrationTestExtension();
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT + 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withJpa();
|
||||
|
||||
private final Spec11PipelineOptions options =
|
||||
PipelineOptionsFactory.create().as(Spec11PipelineOptions.class);
|
||||
|
||||
@@ -146,7 +141,6 @@ class Spec11PipelineTest {
|
||||
options.setDate(DATE);
|
||||
options.setSafeBrowsingApiKey(SAFE_BROWSING_API_KEY);
|
||||
options.setReportingBucketUrl(reportingBucketUrl.getAbsolutePath());
|
||||
options.setDatabase("DATASTORE");
|
||||
threatMatches =
|
||||
pipeline.apply(
|
||||
Create.of(
|
||||
@@ -199,7 +193,6 @@ class Spec11PipelineTest {
|
||||
@Test
|
||||
void testSuccess_fullSqlPipeline() throws Exception {
|
||||
setupCloudSql();
|
||||
options.setDatabase("CLOUD_SQL");
|
||||
EvaluateSafeBrowsingFn safeBrowsingFn =
|
||||
new EvaluateSafeBrowsingFn(
|
||||
SAFE_BROWSING_API_KEY,
|
||||
|
||||
@@ -25,7 +25,6 @@ import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptio
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ReadOnlyModeEppException;
|
||||
import google.registry.flows.FlowUtils.NotLoggedInException;
|
||||
import google.registry.flows.ResourceFlowTestCase;
|
||||
import google.registry.flows.contact.ContactFlowUtils.BadInternationalizedPostalInfoException;
|
||||
@@ -33,10 +32,8 @@ import google.registry.flows.contact.ContactFlowUtils.DeclineContactDisclosureFi
|
||||
import google.registry.flows.exceptions.ResourceAlreadyExistsForThisClientException;
|
||||
import google.registry.flows.exceptions.ResourceCreateContentionException;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Unit tests for {@link ContactCreateFlow}. */
|
||||
@@ -137,12 +134,4 @@ class ContactCreateFlowTest extends ResourceFlowTestCase<ContactCreateFlow, Cont
|
||||
runFlow();
|
||||
assertIcannReportingActivityFieldLogged("srs-cont-create");
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testModification_duringReadOnlyPhase() {
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryReadOnly(clock);
|
||||
EppException thrown = assertThrows(ReadOnlyModeEppException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ReadOnlyModeEppException;
|
||||
import google.registry.flows.FlowUtils.NotLoggedInException;
|
||||
import google.registry.flows.ResourceFlowTestCase;
|
||||
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
||||
@@ -52,10 +51,8 @@ import google.registry.model.tld.Registry;
|
||||
import google.registry.model.transfer.TransferData;
|
||||
import google.registry.model.transfer.TransferResponse;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import google.registry.testing.TestSqlOnly;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -224,24 +221,6 @@ class ContactDeleteFlowTest extends ResourceFlowTestCase<ContactDeleteFlow, Cont
|
||||
assertIcannReportingActivityFieldLogged("srs-cont-delete");
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testModification_duringNoAsyncPhase() throws Exception {
|
||||
persistActiveContact(getUniqueIdFromCommand());
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryNoAsync(clock);
|
||||
EppException thrown = assertThrows(ReadOnlyModeEppException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testModification_duringReadOnlyPhase() throws Exception {
|
||||
persistActiveContact(getUniqueIdFromCommand());
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryReadOnly(clock);
|
||||
EppException thrown = assertThrows(ReadOnlyModeEppException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
|
||||
private void assertSqlDeleteSuccess(HistoryEntry.Type... historyEntryTypes) throws Exception {
|
||||
assertThat(reloadResourceByForeignKey()).isNull();
|
||||
assertAboutContacts()
|
||||
|
||||
@@ -26,7 +26,6 @@ import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptio
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ReadOnlyModeEppException;
|
||||
import google.registry.flows.FlowUtils.NotLoggedInException;
|
||||
import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException;
|
||||
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
||||
@@ -42,10 +41,8 @@ import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.transfer.TransferData;
|
||||
import google.registry.model.transfer.TransferResponse;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
/** Unit tests for {@link ContactTransferApproveFlow}. */
|
||||
@@ -269,12 +266,4 @@ class ContactTransferApproveFlowTest
|
||||
runFlow();
|
||||
assertIcannReportingActivityFieldLogged("srs-cont-transfer-approve");
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testModification_duringReadOnlyPhase() {
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryReadOnly(clock);
|
||||
EppException thrown = assertThrows(ReadOnlyModeEppException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptio
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ReadOnlyModeEppException;
|
||||
import google.registry.flows.FlowUtils.NotLoggedInException;
|
||||
import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException;
|
||||
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
||||
@@ -39,10 +38,8 @@ import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.transfer.TransferData;
|
||||
import google.registry.model.transfer.TransferResponse;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
/** Unit tests for {@link ContactTransferCancelFlow}. */
|
||||
@@ -255,12 +252,4 @@ class ContactTransferCancelFlowTest
|
||||
runFlow();
|
||||
assertIcannReportingActivityFieldLogged("srs-cont-transfer-cancel");
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testModification_duringReadOnlyPhase() {
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryReadOnly(clock);
|
||||
EppException thrown = assertThrows(ReadOnlyModeEppException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptio
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ReadOnlyModeEppException;
|
||||
import google.registry.flows.FlowUtils.NotLoggedInException;
|
||||
import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException;
|
||||
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
||||
@@ -41,10 +40,8 @@ import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.transfer.TransferData;
|
||||
import google.registry.model.transfer.TransferResponse;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
/** Unit tests for {@link ContactTransferRejectFlow}. */
|
||||
@@ -268,12 +265,4 @@ class ContactTransferRejectFlowTest
|
||||
runFlow();
|
||||
assertIcannReportingActivityFieldLogged("srs-cont-transfer-reject");
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testModification_duringReadOnlyPhase() {
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryReadOnly(clock);
|
||||
EppException thrown = assertThrows(ReadOnlyModeEppException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ReadOnlyModeEppException;
|
||||
import google.registry.flows.FlowUtils.NotLoggedInException;
|
||||
import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException;
|
||||
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
||||
@@ -52,10 +51,8 @@ import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.transfer.ContactTransferData;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
@@ -317,12 +314,4 @@ class ContactTransferRequestFlowTest
|
||||
runFlow();
|
||||
assertIcannReportingActivityFieldLogged("srs-cont-transfer-request");
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testModification_duringReadOnlyPhase() {
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryReadOnly(clock);
|
||||
EppException thrown = assertThrows(ReadOnlyModeEppException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ReadOnlyModeEppException;
|
||||
import google.registry.flows.FlowUtils.NotLoggedInException;
|
||||
import google.registry.flows.ResourceFlowTestCase;
|
||||
import google.registry.flows.ResourceFlowUtils.AddRemoveSameValueException;
|
||||
@@ -43,10 +42,8 @@ import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.PostalInfo;
|
||||
import google.registry.model.contact.PostalInfo.Type;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
|
||||
/** Unit tests for {@link ContactUpdateFlow}. */
|
||||
@DualDatabaseTest
|
||||
@@ -430,13 +427,4 @@ class ContactUpdateFlowTest extends ResourceFlowTestCase<ContactUpdateFlow, Cont
|
||||
runFlow();
|
||||
assertIcannReportingActivityFieldLogged("srs-cont-update");
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testModification_duringReadOnlyPhase() throws Exception {
|
||||
persistActiveContact(getUniqueIdFromCommand());
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryReadOnly(clock);
|
||||
EppException thrown = assertThrows(ReadOnlyModeEppException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,6 @@ import com.google.common.collect.Ordering;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.config.RegistryConfig;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ReadOnlyModeEppException;
|
||||
import google.registry.flows.EppException.UnimplementedExtensionException;
|
||||
import google.registry.flows.EppRequestSource;
|
||||
import google.registry.flows.ExtensionManager.UndeclaredServiceExtensionException;
|
||||
@@ -175,11 +174,9 @@ import google.registry.model.tld.Registry.TldState;
|
||||
import google.registry.model.tld.Registry.TldType;
|
||||
import google.registry.monitoring.whitebox.EppMetric;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TaskQueueHelper.TaskMatcher;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@@ -845,15 +842,6 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
doSuccessfulTest();
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testSuccess_inNoAsyncPhase() throws Exception {
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryNoAsync(clock);
|
||||
persistContactsAndHosts();
|
||||
runFlowAssertResponse(
|
||||
loadFile("domain_create_response_noasync.xml", ImmutableMap.of("DOMAIN", "example.tld")));
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testSuccess_maxNumberOfNameservers() throws Exception {
|
||||
setEppInput("domain_create_13_nameservers.xml");
|
||||
@@ -2611,15 +2599,6 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
assertThat(eppMetric.getCommandName()).hasValue("DomainCreate");
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testModification_duringReadOnlyPhase() {
|
||||
persistContactsAndHosts();
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryReadOnly(clock);
|
||||
EppException thrown = assertThrows(ReadOnlyModeEppException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testGetRenewalPriceInfo_isAnchorTenantWithoutToken_returnsNonPremiumAndNullPrice() {
|
||||
assertThat(
|
||||
|
||||
@@ -67,7 +67,6 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import google.registry.batch.ResaveEntityAction;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ReadOnlyModeEppException;
|
||||
import google.registry.flows.EppException.UnimplementedExtensionException;
|
||||
import google.registry.flows.EppRequestSource;
|
||||
import google.registry.flows.FlowUtils.NotLoggedInException;
|
||||
@@ -102,10 +101,8 @@ import google.registry.model.transfer.DomainTransferData;
|
||||
import google.registry.model.transfer.TransferResponse;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.testing.CloudTasksHelper.TaskMatcher;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import java.util.Map;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
@@ -1244,13 +1241,4 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain
|
||||
EppException thrown = assertThrows(UnimplementedExtensionException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testModification_duringReadOnlyPhase() throws Exception {
|
||||
setUpSuccessfulTest();
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryReadOnly(clock);
|
||||
EppException thrown = assertThrows(ReadOnlyModeEppException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ReadOnlyModeEppException;
|
||||
import google.registry.flows.EppRequestSource;
|
||||
import google.registry.flows.FlowUtils.NotLoggedInException;
|
||||
import google.registry.flows.FlowUtils.UnknownCurrencyEppException;
|
||||
@@ -77,11 +76,9 @@ import google.registry.model.reporting.DomainTransactionRecord;
|
||||
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.SetClockExtension;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import java.util.Map;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
@@ -902,20 +899,4 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
|
||||
TransactionReportField.netRenewsFieldFromYears(5),
|
||||
1));
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testModification_duringReadOnlyPhase() throws Exception {
|
||||
persistDomain();
|
||||
DomainBase domain = reloadResourceByForeignKey();
|
||||
persistResource(
|
||||
domain
|
||||
.asBuilder()
|
||||
.setRegistrationExpirationTime(domain.getRegistrationExpirationTime().minusYears(1))
|
||||
.build());
|
||||
clock.setTo(clock.nowUtc().minusSeconds(2));
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryReadOnly(clock);
|
||||
EppException thrown = assertThrows(ReadOnlyModeEppException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,6 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ReadOnlyModeEppException;
|
||||
import google.registry.flows.EppException.UnimplementedExtensionException;
|
||||
import google.registry.flows.FlowUtils.NotLoggedInException;
|
||||
import google.registry.flows.FlowUtils.UnknownCurrencyEppException;
|
||||
@@ -76,10 +75,8 @@ import google.registry.model.reporting.DomainTransactionRecord;
|
||||
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import org.joda.money.Money;
|
||||
@@ -801,13 +798,4 @@ class DomainRestoreRequestFlowTest
|
||||
assertThat(thrown).hasMessageThat().contains("domain restore reports are not supported");
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testModification_duringReadOnlyPhase() throws Exception {
|
||||
persistPendingDeleteDomain();
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryReadOnly(clock);
|
||||
EppException thrown = assertThrows(ReadOnlyModeEppException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.collect.Ordering;
|
||||
import com.google.common.collect.Streams;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ReadOnlyModeEppException;
|
||||
import google.registry.flows.FlowUtils.NotLoggedInException;
|
||||
import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException;
|
||||
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
||||
@@ -74,10 +73,8 @@ import google.registry.model.transfer.DomainTransferData;
|
||||
import google.registry.model.transfer.TransferResponse.DomainTransferResponse;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Stream;
|
||||
import org.joda.money.Money;
|
||||
@@ -678,12 +675,4 @@ class DomainTransferApproveFlowTest
|
||||
domain.getRegistrationExpirationTime());
|
||||
assertHistoryEntriesDoNotContainTransferBillingEventsOrGracePeriods();
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testModification_duringReadOnlyPhase() {
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryReadOnly(clock);
|
||||
EppException thrown = assertThrows(ReadOnlyModeEppException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ReadOnlyModeEppException;
|
||||
import google.registry.flows.FlowUtils.NotLoggedInException;
|
||||
import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException;
|
||||
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
||||
@@ -57,10 +56,8 @@ import google.registry.model.tld.Registry;
|
||||
import google.registry.model.transfer.DomainTransferData;
|
||||
import google.registry.model.transfer.TransferResponse.DomainTransferResponse;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -420,12 +417,4 @@ class DomainTransferCancelFlowTest
|
||||
assertThat(persistedEntry.getDomainTransactionRecords())
|
||||
.containsExactly(previousSuccessRecord.asBuilder().setReportAmount(-1).build());
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testModification_duringReadOnlyPhase() {
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryReadOnly(clock);
|
||||
EppException thrown = assertThrows(ReadOnlyModeEppException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ReadOnlyModeEppException;
|
||||
import google.registry.flows.FlowUtils.NotLoggedInException;
|
||||
import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException;
|
||||
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
||||
@@ -59,10 +58,8 @@ import google.registry.model.tld.Registry;
|
||||
import google.registry.model.transfer.TransferData;
|
||||
import google.registry.model.transfer.TransferResponse;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -388,12 +385,4 @@ class DomainTransferRejectFlowTest
|
||||
previousSuccessRecord.asBuilder().setReportAmount(-1).build(),
|
||||
DomainTransactionRecord.create("tld", clock.nowUtc(), TRANSFER_NACKED, 1));
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testModification_duringReadOnlyPhase() {
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryReadOnly(clock);
|
||||
EppException thrown = assertThrows(ReadOnlyModeEppException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,6 @@ import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Streams;
|
||||
import google.registry.batch.ResaveEntityAction;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ReadOnlyModeEppException;
|
||||
import google.registry.flows.EppRequestSource;
|
||||
import google.registry.flows.FlowUtils.NotLoggedInException;
|
||||
import google.registry.flows.FlowUtils.UnknownCurrencyEppException;
|
||||
@@ -108,10 +107,8 @@ import google.registry.model.transfer.TransferResponse;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.testing.CloudTasksHelper.TaskMatcher;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
@@ -1567,15 +1564,4 @@ class DomainTransferRequestFlowTest
|
||||
DomainTransactionRecord.create(
|
||||
"tld", clock.nowUtc().plusDays(5), TRANSFER_SUCCESSFUL, 1));
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testModification_duringReadOnlyPhase() {
|
||||
setupDomain("example", "tld");
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryReadOnly(clock);
|
||||
EppException thrown =
|
||||
assertThrows(
|
||||
ReadOnlyModeEppException.class, () -> doFailingTest("domain_transfer_request.xml"));
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,6 @@ import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.config.RegistryConfig;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ReadOnlyModeEppException;
|
||||
import google.registry.flows.EppException.UnimplementedExtensionException;
|
||||
import google.registry.flows.EppRequestSource;
|
||||
import google.registry.flows.FlowUtils.NotLoggedInException;
|
||||
@@ -106,10 +105,8 @@ import google.registry.model.poll.PendingActionNotificationResponse.DomainPendin
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import java.util.Optional;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
@@ -1745,14 +1742,4 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
|
||||
runFlowAsSuperuser();
|
||||
assertAboutDomains().that(reloadResourceByForeignKey()).hasNoAutorenewEndTime();
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testModification_duringReadOnlyPhase() throws Exception {
|
||||
persistReferencedEntities();
|
||||
persistDomain();
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryReadOnly(clock);
|
||||
EppException thrown = assertThrows(ReadOnlyModeEppException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ReadOnlyModeEppException;
|
||||
import google.registry.flows.FlowUtils.IpAddressVersionMismatchException;
|
||||
import google.registry.flows.FlowUtils.NotLoggedInException;
|
||||
import google.registry.flows.ResourceFlowTestCase;
|
||||
@@ -55,10 +54,8 @@ import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Unit tests for {@link HostCreateFlow}. */
|
||||
@@ -329,12 +326,4 @@ class HostCreateFlowTest extends ResourceFlowTestCase<HostCreateFlow, HostResour
|
||||
runFlow();
|
||||
assertIcannReportingActivityFieldLogged("srs-host-create");
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testModification_duringReadOnlyPhase() {
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryReadOnly(clock);
|
||||
EppException thrown = assertThrows(ReadOnlyModeEppException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ReadOnlyModeEppException;
|
||||
import google.registry.flows.FlowUtils.NotLoggedInException;
|
||||
import google.registry.flows.ResourceFlowTestCase;
|
||||
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
||||
@@ -51,10 +50,8 @@ import google.registry.model.reporting.HistoryEntry.Type;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.model.transfer.DomainTransferData;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
@@ -310,24 +307,6 @@ class HostDeleteFlowTest extends ResourceFlowTestCase<HostDeleteFlow, HostResour
|
||||
assertIcannReportingActivityFieldLogged("srs-host-delete");
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testModification_duringReadOnlyPhase() {
|
||||
persistActiveHost("ns1.example.tld");
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryReadOnly(clock);
|
||||
EppException thrown = assertThrows(ReadOnlyModeEppException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testModification_duringNoAsyncPhase() {
|
||||
persistActiveHost("ns1.example.tld");
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryNoAsync(clock);
|
||||
EppException thrown = assertThrows(ReadOnlyModeEppException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
|
||||
private void assertSqlDeleteSuccess(boolean isSubordinate) throws Exception {
|
||||
assertThat(reloadResourceByForeignKey()).isNull();
|
||||
HostResource deletedHost = reloadResourceByForeignKey(clock.nowUtc().minusMillis(1));
|
||||
|
||||
@@ -47,7 +47,6 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.net.InetAddresses;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ReadOnlyModeEppException;
|
||||
import google.registry.flows.EppRequestSource;
|
||||
import google.registry.flows.FlowUtils.NotLoggedInException;
|
||||
import google.registry.flows.ResourceFlowTestCase;
|
||||
@@ -79,11 +78,9 @@ import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.model.transfer.DomainTransferData;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TaskQueueHelper.TaskMatcher;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import javax.annotation.Nullable;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
@@ -1335,50 +1332,4 @@ class HostUpdateFlowTest extends ResourceFlowTestCase<HostUpdateFlow, HostResour
|
||||
runFlow();
|
||||
assertIcannReportingActivityFieldLogged("srs-host-update");
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testSuccess_nonHostRename_inNoAsyncPhase_succeeds() throws Exception {
|
||||
setEppInput("host_update_name_unchanged.xml");
|
||||
createTld("tld");
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryNoAsync(clock);
|
||||
DomainBase domain = persistActiveDomain("example.tld");
|
||||
HostResource oldHost = persistActiveSubordinateHost(oldHostName(), domain);
|
||||
clock.advanceOneMilli();
|
||||
runFlowAssertResponse(loadFile("generic_success_response.xml"));
|
||||
// The example xml doesn't do a host rename, so reloading the host should work.
|
||||
assertAboutHosts()
|
||||
.that(reloadResourceByForeignKey())
|
||||
.hasLastSuperordinateChange(oldHost.getLastSuperordinateChange())
|
||||
.and()
|
||||
.hasSuperordinateDomain(domain.createVKey())
|
||||
.and()
|
||||
.hasPersistedCurrentSponsorRegistrarId("TheRegistrar")
|
||||
.and()
|
||||
.hasLastTransferTime(null)
|
||||
.and()
|
||||
.hasOnlyOneHistoryEntryWhich()
|
||||
.hasType(HistoryEntry.Type.HOST_UPDATE);
|
||||
assertDnsTasksEnqueued("ns1.example.tld");
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testRename_duringNoAsyncPhase_fails() throws Exception {
|
||||
createTld("tld");
|
||||
persistActiveSubordinateHost(oldHostName(), persistActiveDomain("example.tld"));
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryNoAsync(clock);
|
||||
EppException thrown = assertThrows(ReadOnlyModeEppException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
|
||||
@TestOfyOnly
|
||||
void testModification_duringReadOnlyPhase_fails() throws Exception {
|
||||
createTld("tld");
|
||||
persistActiveSubordinateHost(oldHostName(), persistActiveDomain("example.tld"));
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryReadOnly(clock);
|
||||
EppException thrown = assertThrows(ReadOnlyModeEppException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import google.registry.flows.session.LoginFlow.UnsupportedLanguageException;
|
||||
import google.registry.model.eppoutput.EppOutput;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.Registrar.State;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -123,7 +124,8 @@ public abstract class LoginFlowTestCase extends FlowTestCase<LoginFlow> {
|
||||
|
||||
@Test
|
||||
void testFailure_unknownRegistrar() {
|
||||
deleteResource(getRegistrarBuilder().build());
|
||||
registrar.getContacts().forEach(DatabaseHelper::deleteResource);
|
||||
deleteResource(registrar);
|
||||
doFailingTest("login_valid.xml", BadRegistrarIdException.class);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.index.EppResourceIndex;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
@@ -52,6 +53,7 @@ import java.util.Set;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
@@ -60,6 +62,10 @@ class ChildEntityInputTest {
|
||||
|
||||
private static final DateTime now = DateTime.now(DateTimeZone.UTC);
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withOfy();
|
||||
|
||||
@RegisterExtension
|
||||
final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withDatastoreAndCloudSql().build();
|
||||
|
||||
@@ -24,12 +24,14 @@ import google.registry.model.ofy.CommitLogBucket;
|
||||
import google.registry.model.ofy.CommitLogManifest;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
@@ -44,6 +46,10 @@ final class CommitLogManifestInputTest {
|
||||
private static final DateTime DATE_TIME_NEW = DateTime.parse("2016-12-19T12:01Z");
|
||||
private static final DateTime DATE_TIME_NEW2 = DateTime.parse("2017-12-19T12:00Z");
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withOfy();
|
||||
|
||||
@RegisterExtension
|
||||
final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withDatastoreAndCloudSql().build();
|
||||
|
||||
@@ -37,6 +37,7 @@ import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.model.index.EppResourceIndex;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
@@ -44,6 +45,7 @@ import java.io.ObjectOutputStream;
|
||||
import java.util.HashSet;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
@@ -52,6 +54,10 @@ class EppResourceInputsTest {
|
||||
|
||||
private static final double EPSILON = 0.0001;
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withOfy();
|
||||
|
||||
@RegisterExtension
|
||||
final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withDatastoreAndCloudSql().build();
|
||||
|
||||
@@ -22,7 +22,6 @@ import static org.joda.time.DateTimeZone.UTC;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.model.common.CrossTldSingleton;
|
||||
import google.registry.model.replay.EntityTest.EntityForTesting;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
@@ -43,7 +42,6 @@ public class CreateAutoTimestampTest {
|
||||
|
||||
/** Timestamped class. */
|
||||
@Entity(name = "CatTestEntity")
|
||||
@EntityForTesting
|
||||
@javax.persistence.Entity
|
||||
public static class CreateAutoTimestampTestObject extends CrossTldSingleton {
|
||||
@Ignore @javax.persistence.Id long id = SINGLETON_ID;
|
||||
|
||||
@@ -19,7 +19,6 @@ import static com.google.common.collect.Maps.newHashMap;
|
||||
import static com.google.common.collect.Sets.newHashSet;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.ImmutableObject.cloneEmptyToNull;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -29,7 +28,6 @@ import com.google.common.collect.Iterables;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import google.registry.model.replay.EntityTest.EntityForTesting;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.util.CidrAddressBlock;
|
||||
import java.lang.reflect.Field;
|
||||
@@ -51,6 +49,7 @@ public class ImmutableObjectTest {
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder()
|
||||
.withDatastoreAndCloudSql()
|
||||
.withJpaUnitTestEntities(ValueObject.class)
|
||||
.withOfyTestEntities(ValueObject.class)
|
||||
.build();
|
||||
|
||||
@@ -279,10 +278,9 @@ public class ImmutableObjectTest {
|
||||
|
||||
/** Simple subclass of ImmutableObject. */
|
||||
@Entity
|
||||
@EntityForTesting
|
||||
@javax.persistence.Entity
|
||||
public static class ValueObject extends ImmutableObject {
|
||||
@Id
|
||||
long id;
|
||||
@Id @javax.persistence.Id long id;
|
||||
|
||||
String value;
|
||||
|
||||
@@ -294,32 +292,6 @@ public class ImmutableObjectTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testToHydratedString_skipsDoNotHydrate() {
|
||||
RootObject root = new RootObject();
|
||||
root.hydrateMe = Key.create(persistResource(ValueObject.create(1, "foo")));
|
||||
root.skipMe = Key.create(persistResource(ValueObject.create(2, "bar")));
|
||||
String hydratedString = root.toHydratedString();
|
||||
assertThat(hydratedString).contains("foo");
|
||||
assertThat(hydratedString).doesNotContain("bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testToHydratedString_expandsMaps() {
|
||||
RootObject root = new RootObject();
|
||||
root.map = ImmutableMap.of("foo", Key.create(persistResource(ValueObject.create(1, "bar"))));
|
||||
String hydratedString = root.toHydratedString();
|
||||
assertThat(hydratedString).contains("foo");
|
||||
assertThat(hydratedString).contains("bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testToHydratedString_expandsCollections() {
|
||||
RootObject root = new RootObject();
|
||||
root.set = ImmutableSet.of(Key.create(persistResource(ValueObject.create(1, "foo"))));
|
||||
assertThat(root.toHydratedString()).contains("foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInsignificantFields() {
|
||||
HasInsignificantFields instance1 =
|
||||
|
||||
@@ -23,7 +23,6 @@ import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.model.common.CrossTldSingleton;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.replay.EntityTest.EntityForTesting;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
@@ -59,7 +58,6 @@ public class UpdateAutoTimestampTest {
|
||||
/** Timestamped class. */
|
||||
@Entity(name = "UatTestEntity")
|
||||
@javax.persistence.Entity
|
||||
@EntityForTesting
|
||||
public static class UpdateAutoTimestampTestObject extends CrossTldSingleton {
|
||||
@Ignore @javax.persistence.Id long id = SINGLETON_ID;
|
||||
UpdateAutoTimestamp updateTime = UpdateAutoTimestamp.create(null);
|
||||
|
||||
-217
@@ -1,217 +0,0 @@
|
||||
// Copyright 2021 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model.common;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState.DATASTORE_ONLY;
|
||||
import static google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState.DATASTORE_PRIMARY;
|
||||
import static google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState.DATASTORE_PRIMARY_NO_ASYNC;
|
||||
import static google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState.DATASTORE_PRIMARY_READ_ONLY;
|
||||
import static google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState.SQL_ONLY;
|
||||
import static google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState.SQL_PRIMARY;
|
||||
import static google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState.SQL_PRIMARY_READ_ONLY;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import google.registry.model.EntityTestCase;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
import google.registry.model.domain.token.AllocationToken.TokenType;
|
||||
import google.registry.persistence.transaction.TransactionManagerFactory.ReadOnlyModeException;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Tests for {@link DatabaseMigrationStateSchedule}. */
|
||||
public class DatabaseMigrationStateScheduleTest extends EntityTestCase {
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
fakeClock.setAutoIncrementByOneMilli();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void afterEach() {
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEmpty_returnsDatastoreOnlyMap() {
|
||||
assertThat(DatabaseMigrationStateSchedule.getUncached())
|
||||
.isEqualTo(DatabaseMigrationStateSchedule.DEFAULT_TRANSITION_MAP);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testValidTransitions() {
|
||||
// First, verify that no-ops are safe
|
||||
for (MigrationState migrationState : MigrationState.values()) {
|
||||
runValidTransition(migrationState, migrationState);
|
||||
}
|
||||
|
||||
// Next, the transitions that will actually cause a change
|
||||
runValidTransition(DATASTORE_ONLY, DATASTORE_PRIMARY);
|
||||
|
||||
runValidTransition(DATASTORE_PRIMARY, DATASTORE_ONLY);
|
||||
runValidTransition(DATASTORE_PRIMARY, DATASTORE_PRIMARY_NO_ASYNC);
|
||||
runValidTransition(DATASTORE_PRIMARY_NO_ASYNC, DATASTORE_PRIMARY_READ_ONLY);
|
||||
|
||||
runValidTransition(DATASTORE_PRIMARY_READ_ONLY, DATASTORE_ONLY);
|
||||
runValidTransition(DATASTORE_PRIMARY_READ_ONLY, DATASTORE_PRIMARY);
|
||||
runValidTransition(DATASTORE_PRIMARY_READ_ONLY, DATASTORE_PRIMARY_NO_ASYNC);
|
||||
runValidTransition(DATASTORE_PRIMARY_READ_ONLY, SQL_PRIMARY_READ_ONLY);
|
||||
runValidTransition(DATASTORE_PRIMARY_READ_ONLY, SQL_PRIMARY);
|
||||
|
||||
runValidTransition(SQL_PRIMARY_READ_ONLY, DATASTORE_PRIMARY_READ_ONLY);
|
||||
runValidTransition(SQL_PRIMARY_READ_ONLY, SQL_PRIMARY);
|
||||
|
||||
runValidTransition(SQL_PRIMARY, SQL_PRIMARY_READ_ONLY);
|
||||
runValidTransition(SQL_PRIMARY, SQL_ONLY);
|
||||
|
||||
runValidTransition(SQL_ONLY, SQL_PRIMARY);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInvalidTransitions() {
|
||||
runInvalidTransition(DATASTORE_ONLY, DATASTORE_PRIMARY_READ_ONLY);
|
||||
runInvalidTransition(DATASTORE_ONLY, SQL_PRIMARY_READ_ONLY);
|
||||
runInvalidTransition(DATASTORE_ONLY, SQL_PRIMARY);
|
||||
runInvalidTransition(DATASTORE_ONLY, SQL_ONLY);
|
||||
|
||||
runInvalidTransition(DATASTORE_PRIMARY, DATASTORE_PRIMARY_READ_ONLY);
|
||||
runInvalidTransition(DATASTORE_PRIMARY, SQL_PRIMARY_READ_ONLY);
|
||||
runInvalidTransition(DATASTORE_PRIMARY, SQL_PRIMARY);
|
||||
runInvalidTransition(DATASTORE_PRIMARY, SQL_ONLY);
|
||||
|
||||
runInvalidTransition(DATASTORE_PRIMARY_READ_ONLY, SQL_ONLY);
|
||||
|
||||
runInvalidTransition(SQL_PRIMARY_READ_ONLY, DATASTORE_ONLY);
|
||||
runInvalidTransition(SQL_PRIMARY_READ_ONLY, DATASTORE_PRIMARY);
|
||||
runInvalidTransition(SQL_PRIMARY_READ_ONLY, SQL_ONLY);
|
||||
|
||||
runInvalidTransition(SQL_PRIMARY, DATASTORE_ONLY);
|
||||
runInvalidTransition(SQL_PRIMARY, DATASTORE_PRIMARY);
|
||||
runInvalidTransition(SQL_PRIMARY, DATASTORE_PRIMARY_READ_ONLY);
|
||||
|
||||
runInvalidTransition(SQL_ONLY, DATASTORE_ONLY);
|
||||
runInvalidTransition(SQL_ONLY, DATASTORE_PRIMARY);
|
||||
runInvalidTransition(SQL_ONLY, DATASTORE_PRIMARY_READ_ONLY);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_newMapImpliesInvalidChangeNow() {
|
||||
DateTime startTime = fakeClock.nowUtc();
|
||||
fakeClock.advanceBy(Duration.standardHours(6));
|
||||
|
||||
// The new map is valid by itself, but not with the current state of DATASTORE_ONLY because the
|
||||
// new map implies that the current state is DATASTORE_PRIMARY_READ_ONLY
|
||||
ImmutableSortedMap<DateTime, MigrationState> nowInvalidMap =
|
||||
ImmutableSortedMap.<DateTime, MigrationState>naturalOrder()
|
||||
.put(START_OF_TIME, DATASTORE_ONLY)
|
||||
.put(startTime.plusHours(1), DATASTORE_PRIMARY)
|
||||
.put(startTime.plusHours(2), DATASTORE_PRIMARY_NO_ASYNC)
|
||||
.put(startTime.plusHours(3), DATASTORE_PRIMARY_READ_ONLY)
|
||||
.build();
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> jpaTm().transact(() -> DatabaseMigrationStateSchedule.set(nowInvalidMap)));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.isEqualTo(
|
||||
"Cannot transition from current state-as-of-now DATASTORE_ONLY "
|
||||
+ "to new state-as-of-now DATASTORE_PRIMARY_READ_ONLY");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_notInTransaction() {
|
||||
IllegalStateException thrown =
|
||||
assertThrows(
|
||||
IllegalStateException.class,
|
||||
() ->
|
||||
DatabaseMigrationStateSchedule.set(
|
||||
DatabaseMigrationStateSchedule.DEFAULT_TRANSITION_MAP.toValueMap()));
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("Not in a transaction");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_factoryUsesSchedule() {
|
||||
assertThat(tm().isOfy()).isTrue();
|
||||
// set the schedule to have converted to SQL_PRIMARY in the past
|
||||
fakeClock.setTo(START_OF_TIME.plusDays(1));
|
||||
runValidTransition(DATASTORE_PRIMARY_READ_ONLY, SQL_PRIMARY);
|
||||
assertThat(tm().isOfy()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_factoryUsesReadOnly() {
|
||||
createTld("tld");
|
||||
fakeClock.setTo(START_OF_TIME.plusDays(1));
|
||||
AllocationToken token =
|
||||
new AllocationToken.Builder().setToken("token").setTokenType(TokenType.SINGLE_USE).build();
|
||||
runValidTransition(DATASTORE_PRIMARY, DATASTORE_PRIMARY_NO_ASYNC);
|
||||
runValidTransition(DATASTORE_PRIMARY_NO_ASYNC, DATASTORE_PRIMARY_READ_ONLY);
|
||||
assertThrows(ReadOnlyModeException.class, () -> persistResource(token));
|
||||
runValidTransition(DATASTORE_PRIMARY_READ_ONLY, SQL_PRIMARY_READ_ONLY);
|
||||
assertThrows(ReadOnlyModeException.class, () -> persistResource(token));
|
||||
runValidTransition(SQL_PRIMARY_READ_ONLY, SQL_PRIMARY);
|
||||
persistResource(token);
|
||||
}
|
||||
|
||||
private void runValidTransition(MigrationState from, MigrationState to) {
|
||||
ImmutableSortedMap<DateTime, MigrationState> transitions =
|
||||
createMapEndingWithTransition(from, to);
|
||||
jpaTm().transact(() -> DatabaseMigrationStateSchedule.set(transitions));
|
||||
assertThat(DatabaseMigrationStateSchedule.getUncached().toValueMap())
|
||||
.containsExactlyEntriesIn(transitions);
|
||||
}
|
||||
|
||||
private void runInvalidTransition(MigrationState from, MigrationState to) {
|
||||
ImmutableSortedMap<DateTime, MigrationState> transitions =
|
||||
createMapEndingWithTransition(from, to);
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> jpaTm().transact(() -> DatabaseMigrationStateSchedule.set(transitions)));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.isEqualTo(
|
||||
String.format("validStateTransitions map cannot transition from %s to %s.", from, to));
|
||||
}
|
||||
|
||||
// Create a transition map that is valid up to the "from" transition, then add the "to" transition
|
||||
private ImmutableSortedMap<DateTime, MigrationState> createMapEndingWithTransition(
|
||||
MigrationState from, MigrationState to) {
|
||||
ImmutableSortedMap.Builder<DateTime, MigrationState> builder =
|
||||
ImmutableSortedMap.naturalOrder();
|
||||
builder.put(START_OF_TIME, DATASTORE_ONLY);
|
||||
MigrationState[] allMigrationStates = MigrationState.values();
|
||||
for (int i = 0; i < allMigrationStates.length; i++) {
|
||||
builder.put(fakeClock.nowUtc().plusMinutes(i), allMigrationStates[i]);
|
||||
if (allMigrationStates[i].equals(from)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
builder.put(fakeClock.nowUtc().plusDays(1), to);
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
@@ -23,8 +23,12 @@ import static google.registry.testing.DatabaseHelper.cloneAndSetAutoTimestamps;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.newDomainBase;
|
||||
import static google.registry.testing.DatabaseHelper.newHostResource;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveContact;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveDomain;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveHost;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static google.registry.testing.DomainBaseSubject.assertAboutDomains;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static org.joda.money.CurrencyUnit.USD;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
@@ -41,6 +45,7 @@ import google.registry.model.EntityTestCase;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.ImmutableObjectSubject;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.billing.BillingEvent.Flag;
|
||||
import google.registry.model.billing.BillingEvent.Reason;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.DesignatedContact.Type;
|
||||
@@ -70,50 +75,55 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
private DomainBase domain;
|
||||
private VKey<BillingEvent.OneTime> oneTimeBillKey;
|
||||
private VKey<BillingEvent.Recurring> recurringBillKey;
|
||||
private Key<HistoryEntry> historyEntryKey;
|
||||
private DomainHistory domainHistory;
|
||||
private VKey<ContactResource> contact1Key, contact2Key;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
createTld("com");
|
||||
VKey<DomainBase> domainKey = VKey.from(Key.create(null, DomainBase.class, "4-COM"));
|
||||
VKey<HostResource> hostKey =
|
||||
domain = persistActiveDomain("example.com");
|
||||
VKey<HostResource> hostKey = persistActiveHost("ns1.example.com").createVKey();
|
||||
contact1Key = persistActiveContact("contact_id1").createVKey();
|
||||
contact2Key = persistActiveContact("contact_id1").createVKey();
|
||||
domainHistory =
|
||||
persistResource(
|
||||
new HostResource.Builder()
|
||||
.setHostName("ns1.example.com")
|
||||
.setSuperordinateDomain(domainKey)
|
||||
.setRepoId("1-COM")
|
||||
new DomainHistory.Builder()
|
||||
.setDomainRepoId(domain.createVKey().getOfyKey().getName())
|
||||
.setModificationTime(fakeClock.nowUtc())
|
||||
.setType(HistoryEntry.Type.DOMAIN_CREATE)
|
||||
.setRegistrarId("TheRegistrar")
|
||||
.build());
|
||||
oneTimeBillKey =
|
||||
persistResource(
|
||||
new BillingEvent.OneTime.Builder()
|
||||
// Use SERVER_STATUS so we don't have to add a period.
|
||||
.setReason(Reason.SERVER_STATUS)
|
||||
.setTargetId(domain.getDomainName())
|
||||
.setRegistrarId(domain.getCurrentSponsorRegistrarId())
|
||||
.setDomainRepoId(domain.getRepoId())
|
||||
.setBillingTime(DateTime.now(UTC))
|
||||
.setCost(Money.of(USD, 100))
|
||||
.setEventTime(DateTime.now(UTC).plusYears(1))
|
||||
.setParent(domainHistory)
|
||||
.build())
|
||||
.createVKey();
|
||||
contact1Key =
|
||||
recurringBillKey =
|
||||
persistResource(
|
||||
new ContactResource.Builder()
|
||||
.setContactId("contact_id1")
|
||||
.setRepoId("2-COM")
|
||||
new BillingEvent.Recurring.Builder()
|
||||
.setReason(Reason.RENEW)
|
||||
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
|
||||
.setTargetId(domain.getDomainName())
|
||||
.setRegistrarId(domain.getCurrentSponsorRegistrarId())
|
||||
.setDomainRepoId(domain.getRepoId())
|
||||
.setEventTime(DateTime.now(UTC).plusYears(1))
|
||||
.setRecurrenceEndTime(END_OF_TIME)
|
||||
.setParent(domainHistory)
|
||||
.build())
|
||||
.createVKey();
|
||||
contact2Key =
|
||||
persistResource(
|
||||
new ContactResource.Builder()
|
||||
.setContactId("contact_id2")
|
||||
.setRepoId("3-COM")
|
||||
.build())
|
||||
.createVKey();
|
||||
historyEntryKey =
|
||||
Key.create(
|
||||
persistResource(
|
||||
new DomainHistory.Builder()
|
||||
.setDomainRepoId(domainKey.getOfyKey().getName())
|
||||
.setModificationTime(fakeClock.nowUtc())
|
||||
.setType(HistoryEntry.Type.DOMAIN_CREATE)
|
||||
.setRegistrarId("aregistrar")
|
||||
.build()));
|
||||
oneTimeBillKey = VKey.from(Key.create(historyEntryKey, BillingEvent.OneTime.class, 1));
|
||||
recurringBillKey = VKey.from(Key.create(historyEntryKey, BillingEvent.Recurring.class, 2));
|
||||
VKey<PollMessage.Autorenew> autorenewPollKey =
|
||||
VKey.from(Key.create(historyEntryKey, PollMessage.Autorenew.class, 3));
|
||||
VKey.from(Key.create(Key.create(domainHistory), PollMessage.Autorenew.class, 3));
|
||||
VKey<PollMessage.OneTime> onetimePollKey =
|
||||
VKey.from(Key.create(historyEntryKey, PollMessage.OneTime.class, 1));
|
||||
VKey.from(Key.create(Key.create(domainHistory), PollMessage.OneTime.class, 1));
|
||||
// Set up a new persisted domain entity.
|
||||
domain =
|
||||
persistResource(
|
||||
@@ -121,9 +131,9 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
new DomainBase.Builder()
|
||||
.setDomainName("example.com")
|
||||
.setRepoId("4-COM")
|
||||
.setCreationRegistrarId("aregistrar")
|
||||
.setCreationRegistrarId("TheRegistrar")
|
||||
.setLastEppUpdateTime(fakeClock.nowUtc())
|
||||
.setLastEppUpdateRegistrarId("AnotherRegistrar")
|
||||
.setLastEppUpdateRegistrarId("NewRegistrar")
|
||||
.setLastTransferTime(fakeClock.nowUtc())
|
||||
.setStatusValues(
|
||||
ImmutableSet.of(
|
||||
@@ -137,7 +147,7 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
.setContacts(ImmutableSet.of(DesignatedContact.create(Type.ADMIN, contact2Key)))
|
||||
.setNameservers(ImmutableSet.of(hostKey))
|
||||
.setSubordinateHosts(ImmutableSet.of("ns1.example.com"))
|
||||
.setPersistedCurrentSponsorRegistrarId("losing")
|
||||
.setPersistedCurrentSponsorRegistrarId("NewRegistrar")
|
||||
.setRegistrationExpirationTime(fakeClock.nowUtc().plusYears(1))
|
||||
.setAuthInfo(DomainAuthInfo.create(PasswordAuth.create("password")))
|
||||
.setDsData(
|
||||
@@ -146,8 +156,8 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
LaunchNotice.create("tcnid", "validatorId", START_OF_TIME, START_OF_TIME))
|
||||
.setTransferData(
|
||||
new DomainTransferData.Builder()
|
||||
.setGainingRegistrarId("gaining")
|
||||
.setLosingRegistrarId("losing")
|
||||
.setGainingRegistrarId("TheRegistrar")
|
||||
.setLosingRegistrarId("NewRegistrar")
|
||||
.setPendingTransferExpirationTime(fakeClock.nowUtc())
|
||||
.setServerApproveEntities(
|
||||
ImmutableSet.of(oneTimeBillKey, recurringBillKey, autorenewPollKey))
|
||||
@@ -165,10 +175,10 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
.addGracePeriod(
|
||||
GracePeriod.create(
|
||||
GracePeriodStatus.ADD,
|
||||
"4-COM",
|
||||
domain.getRepoId(),
|
||||
fakeClock.nowUtc().plusDays(1),
|
||||
"registrar",
|
||||
null))
|
||||
"TheRegistrar",
|
||||
oneTimeBillKey))
|
||||
.setAutorenewEndTime(Optional.of(fakeClock.nowUtc().plusYears(2)))
|
||||
.setDnsRefreshRequestTime(Optional.of(fakeClock.nowUtc()))
|
||||
.build()));
|
||||
@@ -192,28 +202,15 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
|
||||
@Test
|
||||
void testVKeyRestoration() {
|
||||
assertThat(domain.deletePollMessageHistoryId).isEqualTo(historyEntryKey.getId());
|
||||
assertThat(domain.autorenewBillingEventHistoryId).isEqualTo(historyEntryKey.getId());
|
||||
assertThat(domain.autorenewPollMessageHistoryId).isEqualTo(historyEntryKey.getId());
|
||||
assertThat(domain.deletePollMessageHistoryId).isEqualTo(domainHistory.getId());
|
||||
assertThat(domain.autorenewBillingEventHistoryId).isEqualTo(domainHistory.getId());
|
||||
assertThat(domain.autorenewPollMessageHistoryId).isEqualTo(domainHistory.getId());
|
||||
assertThat(domain.getTransferData().getServerApproveBillingEventHistoryId())
|
||||
.isEqualTo(historyEntryKey.getId());
|
||||
.isEqualTo(domainHistory.getId());
|
||||
assertThat(domain.getTransferData().getServerApproveAutorenewEventHistoryId())
|
||||
.isEqualTo(historyEntryKey.getId());
|
||||
.isEqualTo(domainHistory.getId());
|
||||
assertThat(domain.getTransferData().getServerApproveAutorenewPollMessageHistoryId())
|
||||
.isEqualTo(historyEntryKey.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIndexing() throws Exception {
|
||||
verifyDatastoreIndexing(
|
||||
domain,
|
||||
"allContacts.contact",
|
||||
"fullyQualifiedDomainName",
|
||||
"nsHosts",
|
||||
"currentSponsorClientId",
|
||||
"deletionTime",
|
||||
"tld",
|
||||
"autorenewEndTime");
|
||||
.isEqualTo(domainHistory.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -366,7 +363,7 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
VKey<BillingEvent.Recurring> newAutorenewEvent) {
|
||||
assertThat(domain.getTransferData().getTransferStatus())
|
||||
.isEqualTo(TransferStatus.SERVER_APPROVED);
|
||||
assertThat(domain.getCurrentSponsorRegistrarId()).isEqualTo("winner");
|
||||
assertThat(domain.getCurrentSponsorRegistrarId()).isEqualTo("TheRegistrar");
|
||||
assertThat(domain.getLastTransferTime()).isEqualTo(fakeClock.nowUtc().plusDays(1));
|
||||
assertThat(domain.getRegistrationExpirationTime()).isEqualTo(newExpirationTime);
|
||||
assertThat(domain.getAutorenewBillingEvent()).isEqualTo(newAutorenewEvent);
|
||||
@@ -374,18 +371,19 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
|
||||
private void doExpiredTransferTest(DateTime oldExpirationTime) {
|
||||
DomainHistory historyEntry =
|
||||
new DomainHistory.Builder()
|
||||
.setDomain(domain)
|
||||
.setModificationTime(fakeClock.nowUtc())
|
||||
.setRegistrarId(domain.getCurrentSponsorRegistrarId())
|
||||
.setType(HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST)
|
||||
.build();
|
||||
persistResource(
|
||||
new DomainHistory.Builder()
|
||||
.setDomain(domain)
|
||||
.setModificationTime(fakeClock.nowUtc())
|
||||
.setRegistrarId(domain.getCurrentSponsorRegistrarId())
|
||||
.setType(HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST)
|
||||
.build());
|
||||
BillingEvent.OneTime transferBillingEvent =
|
||||
persistResource(
|
||||
new BillingEvent.OneTime.Builder()
|
||||
.setReason(Reason.TRANSFER)
|
||||
.setRegistrarId("winner")
|
||||
.setTargetId("example.com")
|
||||
.setRegistrarId("TheRegistrar")
|
||||
.setTargetId(domain.getDomainName())
|
||||
.setEventTime(fakeClock.nowUtc())
|
||||
.setBillingTime(
|
||||
fakeClock
|
||||
@@ -407,7 +405,7 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
.setTransferStatus(TransferStatus.PENDING)
|
||||
.setTransferRequestTime(fakeClock.nowUtc().minusDays(4))
|
||||
.setPendingTransferExpirationTime(fakeClock.nowUtc().plusDays(1))
|
||||
.setGainingRegistrarId("winner")
|
||||
.setGainingRegistrarId("TheRegistrar")
|
||||
.setServerApproveBillingEvent(transferBillingEvent.createVKey())
|
||||
.setServerApproveEntities(ImmutableSet.of(transferBillingEvent.createVKey()))
|
||||
.build())
|
||||
@@ -418,8 +416,8 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
GracePeriodStatus.ADD,
|
||||
domain.getRepoId(),
|
||||
fakeClock.nowUtc().plusDays(100),
|
||||
"foo",
|
||||
null))
|
||||
"TheRegistrar",
|
||||
oneTimeBillKey))
|
||||
.build();
|
||||
DomainBase afterTransfer = domain.cloneProjectedAtTime(fakeClock.nowUtc().plusDays(1));
|
||||
DateTime newExpirationTime = oldExpirationTime.plusYears(1);
|
||||
@@ -435,7 +433,7 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
.nowUtc()
|
||||
.plusDays(1)
|
||||
.plus(Registry.get("com").getTransferGracePeriodLength()),
|
||||
"winner",
|
||||
"TheRegistrar",
|
||||
transferBillingEvent.createVKey(),
|
||||
afterTransfer.getGracePeriods().iterator().next().getGracePeriodId()));
|
||||
// If we project after the grace period expires all should be the same except the grace period.
|
||||
@@ -491,13 +489,13 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
|
||||
DomainBase beforeAutoRenew = domain.cloneProjectedAtTime(autorenewDateTime.minusDays(1));
|
||||
assertThat(beforeAutoRenew.getLastEppUpdateTime()).isEqualTo(transferRequestDateTime);
|
||||
assertThat(beforeAutoRenew.getLastEppUpdateRegistrarId()).isEqualTo("gaining");
|
||||
assertThat(beforeAutoRenew.getLastEppUpdateRegistrarId()).isEqualTo("TheRegistrar");
|
||||
|
||||
// If autorenew happens before transfer succeeds(before transfer grace period starts as well),
|
||||
// lastEppUpdateClientId should still be the current sponsor client id
|
||||
DomainBase afterAutoRenew = domain.cloneProjectedAtTime(autorenewDateTime.plusDays(1));
|
||||
assertThat(afterAutoRenew.getLastEppUpdateTime()).isEqualTo(autorenewDateTime);
|
||||
assertThat(afterAutoRenew.getLastEppUpdateRegistrarId()).isEqualTo("losing");
|
||||
assertThat(afterAutoRenew.getLastEppUpdateRegistrarId()).isEqualTo("NewRegistrar");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -510,12 +508,12 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
|
||||
DomainBase beforeAutoRenew = domain.cloneProjectedAtTime(autorenewDateTime.minusDays(1));
|
||||
assertThat(beforeAutoRenew.getLastEppUpdateTime()).isEqualTo(transferRequestDateTime);
|
||||
assertThat(beforeAutoRenew.getLastEppUpdateRegistrarId()).isEqualTo("gaining");
|
||||
assertThat(beforeAutoRenew.getLastEppUpdateRegistrarId()).isEqualTo("TheRegistrar");
|
||||
|
||||
DomainBase afterTransferSuccess =
|
||||
domain.cloneProjectedAtTime(transferSuccessDateTime.plusDays(1));
|
||||
assertThat(afterTransferSuccess.getLastEppUpdateTime()).isEqualTo(transferSuccessDateTime);
|
||||
assertThat(afterTransferSuccess.getLastEppUpdateRegistrarId()).isEqualTo("gaining");
|
||||
assertThat(afterTransferSuccess.getLastEppUpdateRegistrarId()).isEqualTo("TheRegistrar");
|
||||
}
|
||||
|
||||
private void setupUnmodifiedDomain(DateTime oldExpirationTime) {
|
||||
@@ -542,7 +540,7 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
|
||||
DomainBase afterAutoRenew = domain.cloneProjectedAtTime(autorenewDateTime.plusDays(1));
|
||||
assertThat(afterAutoRenew.getLastEppUpdateTime()).isEqualTo(autorenewDateTime);
|
||||
assertThat(afterAutoRenew.getLastEppUpdateRegistrarId()).isEqualTo("losing");
|
||||
assertThat(afterAutoRenew.getLastEppUpdateRegistrarId()).isEqualTo("NewRegistrar");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -911,20 +909,8 @@ public class DomainBaseTest extends EntityTestCase {
|
||||
|
||||
@Test
|
||||
void testContactFields() {
|
||||
VKey<ContactResource> contact3Key =
|
||||
persistResource(
|
||||
new ContactResource.Builder()
|
||||
.setContactId("contact_id3")
|
||||
.setRepoId("4-COM")
|
||||
.build())
|
||||
.createVKey();
|
||||
VKey<ContactResource> contact4Key =
|
||||
persistResource(
|
||||
new ContactResource.Builder()
|
||||
.setContactId("contact_id4")
|
||||
.setRepoId("5-COM")
|
||||
.build())
|
||||
.createVKey();
|
||||
VKey<ContactResource> contact3Key = persistActiveContact("contact_id3").createVKey();
|
||||
VKey<ContactResource> contact4Key = persistActiveContact("contact_id4").createVKey();
|
||||
|
||||
// Set all of the contacts.
|
||||
domain.setContactFields(
|
||||
|
||||
@@ -26,12 +26,19 @@ import com.google.common.collect.Iterables;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.EntityTestCase;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link EppResourceIndex}. */
|
||||
class EppResourceIndexTest extends EntityTestCase {
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withOfy();
|
||||
|
||||
private ContactResource contact;
|
||||
|
||||
@BeforeEach
|
||||
|
||||
@@ -27,13 +27,19 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.annotation.Cache;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Tests for {@link CommitLogBucket}. */
|
||||
public class CommitLogBucketTest {
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withOfy();
|
||||
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withDatastoreAndCloudSql().build();
|
||||
|
||||
@@ -27,14 +27,19 @@ import com.googlecode.objectify.annotation.Parent;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.InCrossTld;
|
||||
import google.registry.model.common.EntityGroupRoot;
|
||||
import google.registry.model.replay.EntityTest.EntityForTesting;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link DatastoreTransactionManager}. */
|
||||
public class DatastoreTransactionManagerTest {
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withOfy();
|
||||
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder()
|
||||
@@ -54,7 +59,6 @@ public class DatastoreTransactionManagerTest {
|
||||
}
|
||||
|
||||
@Entity
|
||||
@EntityForTesting
|
||||
@InCrossTld
|
||||
private static class InCrossTldTestEntity extends ImmutableObject {
|
||||
|
||||
|
||||
@@ -34,14 +34,20 @@ import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.testing.TestObject.TestVirtualObject;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests ensuring {@link Ofy} saves transactions to {@link CommitLogManifest}. */
|
||||
public class OfyCommitLogTest {
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withOfy();
|
||||
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder()
|
||||
|
||||
@@ -45,17 +45,17 @@ import google.registry.model.contact.ContactHistory;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.replay.EntityTest.EntityForTesting;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.persistence.transaction.TransactionManagerFactory.ReadOnlyModeException;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import google.registry.util.SystemClock;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.function.Supplier;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
@@ -64,6 +64,10 @@ public class OfyTest {
|
||||
|
||||
private final FakeClock fakeClock = new FakeClock(DateTime.parse("2000-01-01TZ"));
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withOfy();
|
||||
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withDatastoreAndCloudSql().withClock(fakeClock).build();
|
||||
@@ -178,7 +182,6 @@ public class OfyTest {
|
||||
|
||||
/** Simple entity class with lifecycle callbacks. */
|
||||
@com.googlecode.objectify.annotation.Entity
|
||||
@EntityForTesting
|
||||
public static class LifecycleObject extends ImmutableObject {
|
||||
|
||||
@Parent Key<?> parent = getCrossTldKey();
|
||||
@@ -437,12 +440,4 @@ public class OfyTest {
|
||||
// Test the normal loading again to verify that we've restored the original session unchanged.
|
||||
assertThat(auditedOfy().load().entity(someObject).now()).isEqualTo(someObject.asHistoryEntry());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testReadOnly_failsWrite() {
|
||||
Ofy ofy = new Ofy(fakeClock);
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryReadOnly(fakeClock);
|
||||
assertThrows(ReadOnlyModeException.class, () -> ofy.save().entity(someObject).now());
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
// Copyright 2020 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model.replay;
|
||||
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth.assertWithMessage;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Embed;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
import google.registry.model.ModelUtils;
|
||||
import google.registry.model.common.GaeUserIdConverter;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import io.github.classgraph.ClassGraph;
|
||||
import io.github.classgraph.ClassInfo;
|
||||
import io.github.classgraph.ClassInfoList;
|
||||
import io.github.classgraph.ScanResult;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Method;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/**
|
||||
* Test to verify classes implement {@link SqlEntity} and {@link DatastoreEntity} when they should.
|
||||
*/
|
||||
public class EntityTest {
|
||||
|
||||
@RegisterExtension
|
||||
final DatastoreEntityExtension datastoreEntityExtension = new DatastoreEntityExtension();
|
||||
|
||||
private static final ImmutableSet<Class<?>> NON_CONVERTED_CLASSES =
|
||||
ImmutableSet.of(GaeUserIdConverter.class);
|
||||
|
||||
@Test
|
||||
void testSqlEntityPersistence() {
|
||||
try (ScanResult scanResult = scanForClasses()) {
|
||||
// All javax.persistence entities must implement SqlEntity and vice versa
|
||||
ImmutableSet<String> javaxPersistenceClasses =
|
||||
getAllClassesWithAnnotation(scanResult, javax.persistence.Entity.class.getName());
|
||||
ImmutableSet<String> sqlEntityClasses =
|
||||
getClassNames(scanResult.getClassesImplementing(SqlEntity.class.getName()));
|
||||
assertThat(sqlEntityClasses).containsExactlyElementsIn(javaxPersistenceClasses);
|
||||
|
||||
// All com.googlecode.objectify entities must implement DatastoreEntity and vice versa
|
||||
ImmutableSet<String> objectifyClasses =
|
||||
getAllClassesWithAnnotation(
|
||||
scanResult, com.googlecode.objectify.annotation.Entity.class.getName());
|
||||
ImmutableSet<String> datastoreEntityClasses =
|
||||
getClassNames(scanResult.getClassesImplementing(DatastoreEntity.class.getName()));
|
||||
assertThat(datastoreEntityClasses).containsExactlyElementsIn(objectifyClasses);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDatastoreEntityVKeyCreation() {
|
||||
// For replication, we need to be able to convert from Key -> VKey for the relevant classes.
|
||||
// This means that the relevant classes must have non-composite Objectify keys or must have a
|
||||
// createVKey method
|
||||
try (ScanResult scanResult = scanForClasses()) {
|
||||
ImmutableSet<Class<?>> datastoreEntityClasses =
|
||||
getClasses(scanResult.getClassesImplementing(DatastoreEntity.class.getName()));
|
||||
// some classes aren't converted so they aren't relevant
|
||||
ImmutableSet<Class<?>> vkeyConversionNecessaryClasses =
|
||||
datastoreEntityClasses.stream()
|
||||
.filter(clazz -> !DatastoreOnlyEntity.class.isAssignableFrom(clazz))
|
||||
.filter(clazz -> !NonReplicatedEntity.class.isAssignableFrom(clazz))
|
||||
.collect(toImmutableSet());
|
||||
|
||||
ImmutableSet.Builder<Class<?>> failedClasses = new ImmutableSet.Builder<>();
|
||||
for (Class<?> clazz : vkeyConversionNecessaryClasses) {
|
||||
if (hasKeyWithParent(clazz)) {
|
||||
try {
|
||||
Method createVKeyMethod = clazz.getMethod("createVKey", Key.class);
|
||||
if (!createVKeyMethod.getReturnType().equals(VKey.class)) {
|
||||
failedClasses.add(clazz);
|
||||
}
|
||||
} catch (NoSuchMethodException e) {
|
||||
failedClasses.add(clazz);
|
||||
}
|
||||
}
|
||||
}
|
||||
assertWithMessage(
|
||||
"Some DatastoreEntity classes with parents were missing createVKey methods: ")
|
||||
.that(failedClasses.build())
|
||||
.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasKeyWithParent(Class<?> clazz) {
|
||||
return ModelUtils.getAllFields(clazz).values().stream()
|
||||
.anyMatch(field -> field.getAnnotation(Parent.class) != null);
|
||||
}
|
||||
|
||||
private ImmutableSet<String> getAllClassesWithAnnotation(
|
||||
ScanResult scanResult, String annotation) {
|
||||
ImmutableSet.Builder<String> result = new ImmutableSet.Builder<>();
|
||||
ClassInfoList classesWithAnnotation = scanResult.getClassesWithAnnotation(annotation);
|
||||
result.addAll(getClassNames(classesWithAnnotation));
|
||||
classesWithAnnotation.stream()
|
||||
.map(ClassInfo::getSubclasses)
|
||||
.forEach(classInfoList -> result.addAll(getClassNames(classInfoList)));
|
||||
return result.build();
|
||||
}
|
||||
|
||||
private ImmutableSet<Class<?>> getClasses(ClassInfoList classInfoList) {
|
||||
return classInfoList.stream()
|
||||
.filter(ClassInfo::isStandardClass)
|
||||
.map(ClassInfo::loadClass)
|
||||
.filter(
|
||||
clazz ->
|
||||
!clazz.isAnnotationPresent(EntityForTesting.class)
|
||||
&& !clazz.isAnnotationPresent(Embed.class)
|
||||
&& !NON_CONVERTED_CLASSES.contains(clazz)
|
||||
&& !clazz.getName().contains("Test"))
|
||||
.collect(toImmutableSet());
|
||||
}
|
||||
|
||||
private ImmutableSet<String> getClassNames(ClassInfoList classInfoList) {
|
||||
return getClasses(classInfoList).stream().map(Class::getName).collect(toImmutableSet());
|
||||
}
|
||||
|
||||
private ScanResult scanForClasses() {
|
||||
return new ClassGraph()
|
||||
.enableAnnotationInfo()
|
||||
.ignoreClassVisibility()
|
||||
.acceptPackages("google.registry")
|
||||
.scan();
|
||||
}
|
||||
|
||||
/** Entities that are solely used for testing, to avoid scanning them in {@link EntityTest}. */
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface EntityForTesting {}
|
||||
}
|
||||
+6
-2
@@ -27,13 +27,14 @@ import com.googlecode.objectify.annotation.Entity;
|
||||
import google.registry.model.common.CrossTldSingleton;
|
||||
import google.registry.model.ofy.CommitLogManifest;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.replay.EntityTest.EntityForTesting;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import java.util.List;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
@@ -43,11 +44,14 @@ public class CommitLogRevisionsTranslatorFactoryTest {
|
||||
private static final DateTime START_TIME = DateTime.parse("2000-01-01TZ");
|
||||
|
||||
@Entity(name = "ClrtfTestEntity")
|
||||
@EntityForTesting
|
||||
public static class TestObject extends CrossTldSingleton {
|
||||
ImmutableSortedMap<DateTime, Key<CommitLogManifest>> revisions = ImmutableSortedMap.of();
|
||||
}
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withOfy();
|
||||
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder()
|
||||
|
||||
@@ -26,7 +26,6 @@ import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.common.EntityGroupRoot;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.replay.EntityTest.EntityForTesting;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.persistence.BillingVKey.BillingEventVKey;
|
||||
import google.registry.persistence.BillingVKey.BillingRecurrenceVKey;
|
||||
@@ -80,7 +79,6 @@ class BillingVKeyTest {
|
||||
assertThat(persisted).isEqualTo(original);
|
||||
}
|
||||
|
||||
@EntityForTesting
|
||||
@Entity
|
||||
@javax.persistence.Entity
|
||||
private static class BillingVKeyTestEntity extends ImmutableObject {
|
||||
|
||||
@@ -26,7 +26,6 @@ import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.common.EntityGroupRoot;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||
import google.registry.model.replay.EntityTest.EntityForTesting;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
@@ -82,7 +81,6 @@ class DomainHistoryVKeyTest {
|
||||
VKey.create(HistoryEntry.class, new DomainHistoryId("domainRepoId", 10L), ofyKey));
|
||||
}
|
||||
|
||||
@EntityForTesting
|
||||
@Entity
|
||||
@javax.persistence.Entity(name = "TestEntity")
|
||||
private static class TestEntity extends ImmutableObject {
|
||||
|
||||
@@ -22,7 +22,6 @@ import static google.registry.testing.DatabaseHelper.insertInDb;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.replay.NonReplicatedEntity;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaUnitTestExtension;
|
||||
import java.lang.reflect.Method;
|
||||
@@ -169,7 +168,7 @@ class EntityCallbacksListenerTest {
|
||||
}
|
||||
|
||||
@Entity(name = "TestEntity")
|
||||
private static class TestEntity extends ParentEntity implements NonReplicatedEntity {
|
||||
private static class TestEntity extends ParentEntity {
|
||||
@Id String name = "id";
|
||||
int nonTransientField = 0;
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import static google.registry.testing.DatabaseHelper.insertInDb;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.hash.BloomFilter;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.replay.EntityTest.EntityForTesting;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaUnitTestExtension;
|
||||
import javax.persistence.Entity;
|
||||
@@ -49,7 +48,6 @@ class BloomFilterConverterTest {
|
||||
}
|
||||
|
||||
@Entity(name = "TestEntity") // Override entity name to avoid the nested class reference.
|
||||
@EntityForTesting
|
||||
public static class TestEntity extends ImmutableObject {
|
||||
|
||||
@Id String name = "id";
|
||||
|
||||
-2
@@ -20,7 +20,6 @@ import static google.registry.testing.DatabaseHelper.insertInDb;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.replay.EntityTest.EntityForTesting;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaUnitTestExtension;
|
||||
import javax.persistence.Entity;
|
||||
@@ -77,7 +76,6 @@ public class CurrencyUnitConverterTest {
|
||||
}
|
||||
|
||||
@Entity(name = "TestEntity") // Override entity name to avoid the nested class reference.
|
||||
@EntityForTesting
|
||||
public static class TestEntity extends ImmutableObject {
|
||||
|
||||
@Id String name = "id";
|
||||
|
||||
@@ -19,7 +19,6 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
|
||||
import static google.registry.testing.DatabaseHelper.insertInDb;
|
||||
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.replay.EntityTest.EntityForTesting;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaUnitTestExtension;
|
||||
import javax.persistence.Entity;
|
||||
@@ -88,7 +87,6 @@ public class DurationConverterTest {
|
||||
}
|
||||
|
||||
@Entity(name = "TestEntity") // Override entity name to avoid the nested class reference.
|
||||
@EntityForTesting
|
||||
public static class DurationTestEntity extends ImmutableObject {
|
||||
|
||||
@Id String name = "id";
|
||||
|
||||
-2
@@ -21,7 +21,6 @@ import static google.registry.testing.DatabaseHelper.insertInDb;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.net.InetAddresses;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.replay.EntityTest.EntityForTesting;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import java.net.InetAddress;
|
||||
@@ -73,7 +72,6 @@ public class InetAddressSetConverterTest {
|
||||
}
|
||||
|
||||
@Entity(name = "TestEntity") // Override entity name to avoid the nested class reference.
|
||||
@EntityForTesting
|
||||
private static class InetAddressSetTestEntity extends ImmutableObject {
|
||||
|
||||
@Id String name = "id";
|
||||
|
||||
@@ -20,7 +20,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.replay.EntityTest.EntityForTesting;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaUnitTestExtension;
|
||||
import java.math.BigDecimal;
|
||||
@@ -289,7 +288,6 @@ public class JodaMoneyConverterTest {
|
||||
// Override entity name to exclude outer-class name in table name. Not necessary if class is not
|
||||
// inner class.
|
||||
@Entity(name = "TestEntity")
|
||||
@EntityForTesting
|
||||
public static class TestEntity extends ImmutableObject {
|
||||
|
||||
@Id String name = "id";
|
||||
@@ -307,7 +305,6 @@ public class JodaMoneyConverterTest {
|
||||
|
||||
// See comments on the annotation for TestEntity above for reason.
|
||||
@Entity(name = "ComplexTestEntity")
|
||||
@EntityForTesting
|
||||
// This entity is used to test column override for embedded fields and collections.
|
||||
public static class ComplexTestEntity extends ImmutableObject {
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
|
||||
import static google.registry.testing.DatabaseHelper.insertInDb;
|
||||
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.replay.EntityTest;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaUnitTestExtension;
|
||||
@@ -63,7 +62,6 @@ public class LocalDateConverterTest {
|
||||
|
||||
/** Override entity name to avoid the nested class reference. */
|
||||
@Entity(name = "LocalDateConverterTestEntity")
|
||||
@EntityTest.EntityForTesting
|
||||
private static class LocalDateConverterTestEntity extends ImmutableObject {
|
||||
|
||||
@Id String name = "id";
|
||||
|
||||
+10
-19
@@ -27,7 +27,6 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.common.io.Resources;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule;
|
||||
import google.registry.persistence.HibernateSchemaExporter;
|
||||
import google.registry.persistence.NomulusPostgreSql;
|
||||
import google.registry.persistence.PersistenceModule;
|
||||
@@ -168,7 +167,7 @@ abstract class JpaTransactionManagerExtension implements BeforeEachCallback, Aft
|
||||
if (!includeNomulusSchema) {
|
||||
File tempSqlFile = File.createTempFile("tempSqlFile", ".sql");
|
||||
tempSqlFile.deleteOnExit();
|
||||
exporter.export(getTestEntities(), tempSqlFile);
|
||||
exporter.export(extraEntityClasses, tempSqlFile);
|
||||
executeSql(new String(Files.readAllBytes(tempSqlFile.toPath()), StandardCharsets.UTF_8));
|
||||
}
|
||||
assertReasonableNumDbConnections();
|
||||
@@ -238,14 +237,16 @@ abstract class JpaTransactionManagerExtension implements BeforeEachCallback, Aft
|
||||
ResultSet rs =
|
||||
statement.executeQuery(
|
||||
"SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';");
|
||||
ImmutableList.Builder<String> tableNames = new ImmutableList.Builder<>();
|
||||
ImmutableList.Builder<String> tableNamesBuilder = new ImmutableList.Builder<>();
|
||||
while (rs.next()) {
|
||||
tableNames.add('"' + rs.getString(1) + '"');
|
||||
tableNamesBuilder.add('"' + rs.getString(1) + '"');
|
||||
}
|
||||
ImmutableList<String> tableNames = tableNamesBuilder.build();
|
||||
if (!tableNames.isEmpty()) {
|
||||
String sql =
|
||||
String.format("TRUNCATE %s RESTART IDENTITY CASCADE", Joiner.on(',').join(tableNames));
|
||||
executeSql(sql);
|
||||
}
|
||||
String sql =
|
||||
String.format(
|
||||
"TRUNCATE %s RESTART IDENTITY CASCADE", Joiner.on(',').join(tableNames.build()));
|
||||
executeSql(sql);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -344,17 +345,7 @@ abstract class JpaTransactionManagerExtension implements BeforeEachCallback, Aft
|
||||
descriptor.getManagedClassNames().addAll(nonEntityClasses);
|
||||
}
|
||||
|
||||
getTestEntities().stream().map(Class::getName).forEach(descriptor::addClasses);
|
||||
extraEntityClasses.stream().map(Class::getName).forEach(descriptor::addClasses);
|
||||
return Bootstrap.getEntityManagerFactoryBuilder(descriptor, properties).build();
|
||||
}
|
||||
|
||||
private ImmutableList<Class<?>> getTestEntities() {
|
||||
// We have to add the DatabaseMigrationStateSchedule and TransactionEntity classes to extra
|
||||
// entities, as they are required by the transaction manager factory and transaction replication
|
||||
// mechanism, respectively.
|
||||
return Stream.concat(
|
||||
extraEntityClasses.stream(),
|
||||
Stream.of(DatabaseMigrationStateSchedule.class, TransactionEntity.class))
|
||||
.collect(toImmutableList());
|
||||
}
|
||||
}
|
||||
|
||||
-6
@@ -36,7 +36,6 @@ import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaUnitTestExtension;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigInteger;
|
||||
import java.sql.SQLException;
|
||||
@@ -49,7 +48,6 @@ import javax.persistence.IdClass;
|
||||
import javax.persistence.OptimisticLockException;
|
||||
import javax.persistence.RollbackException;
|
||||
import org.hibernate.exception.JDBCConnectionException;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
@@ -84,10 +82,6 @@ class JpaTransactionManagerImplTest {
|
||||
TestEntity.class, TestCompoundIdEntity.class, TestNamedCompoundIdEntity.class)
|
||||
.buildUnitTestExtension();
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT + 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withJpa();
|
||||
|
||||
@Test
|
||||
void transact_succeeds() {
|
||||
assertPersonEmpty();
|
||||
|
||||
-10
@@ -340,16 +340,6 @@ public class ReplicaSimulatingJpaTransactionManager implements JpaTransactionMan
|
||||
return delegate.isOfy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putIgnoringReadOnlyWithoutBackup(Object entity) {
|
||||
delegate.putIgnoringReadOnlyWithoutBackup(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteIgnoringReadOnlyWithoutBackup(VKey<?> key) {
|
||||
delegate.deleteIgnoringReadOnlyWithoutBackup(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void assertDelete(VKey<T> key) {
|
||||
delegate.assertDelete(key);
|
||||
|
||||
+1
-11
@@ -30,11 +30,8 @@ import com.googlecode.objectify.annotation.Id;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.ofy.DatastoreTransactionManager;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.replay.NonReplicatedEntity;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.transaction.TransactionManagerFactory.ReadOnlyModeException;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
@@ -409,13 +406,6 @@ public class TransactionManagerTest {
|
||||
assertThat(tm().transact(() -> tm().loadByKey(theEntity.key())).data).isEqualTo("foo");
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testReadOnly_writeFails() {
|
||||
DatabaseHelper.setMigrationScheduleToDatastorePrimaryReadOnly(fakeClock);
|
||||
assertThrows(ReadOnlyModeException.class, () -> tm().transact(() -> tm().put(theEntity)));
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
|
||||
private static void assertEntityExists(TestEntity entity) {
|
||||
assertThat(tm().transact(() -> tm().exists(entity))).isTrue();
|
||||
}
|
||||
@@ -449,7 +439,7 @@ public class TransactionManagerTest {
|
||||
|
||||
@Entity(name = "TxnMgrTestEntity")
|
||||
@javax.persistence.Entity(name = "TestEntity")
|
||||
private static class TestEntity extends TestEntityBase implements NonReplicatedEntity {
|
||||
private static class TestEntity extends TestEntityBase {
|
||||
|
||||
private String data;
|
||||
|
||||
|
||||
@@ -1,189 +0,0 @@
|
||||
// Copyright 2020 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.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.ofy.ObjectifyService.auditedOfy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.ofyTm;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.ofy.CommitLogManifest;
|
||||
import google.registry.model.ofy.CommitLogMutation;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.StreamCorruptedException;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
class TransactionTest {
|
||||
|
||||
private final FakeClock fakeClock =
|
||||
new FakeClock(DateTime.parse("2000-01-01TZ")).setAutoIncrementByOneMilli();
|
||||
|
||||
@RegisterExtension
|
||||
final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder()
|
||||
.withDatastoreAndCloudSql()
|
||||
.withClock(fakeClock)
|
||||
.withOfyTestEntities(TestEntity.class)
|
||||
.withJpaUnitTestEntities(TestEntity.class)
|
||||
.build();
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
private TestEntity fooEntity, barEntity;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
inject.setStaticField(Ofy.class, "clock", fakeClock);
|
||||
fooEntity = new TestEntity("foo");
|
||||
barEntity = new TestEntity("bar");
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void afterEach() {
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTransactionReplay() {
|
||||
Transaction txn = new Transaction.Builder().addUpdate(fooEntity).addUpdate(barEntity).build();
|
||||
txn.writeToDatastore();
|
||||
|
||||
ofyTm()
|
||||
.transact(
|
||||
() -> {
|
||||
assertThat(ofyTm().loadByKey(fooEntity.key())).isEqualTo(fooEntity);
|
||||
assertThat(ofyTm().loadByKey(barEntity.key())).isEqualTo(barEntity);
|
||||
});
|
||||
|
||||
txn = new Transaction.Builder().addDelete(barEntity.key()).build();
|
||||
txn.writeToDatastore();
|
||||
assertThat(ofyTm().exists(barEntity.key())).isEqualTo(false);
|
||||
|
||||
assertThat(
|
||||
auditedOfy().load().type(CommitLogMutation.class).list().stream()
|
||||
.map(clm -> auditedOfy().load().<TestEntity>fromEntity(clm.getEntity()))
|
||||
.collect(toImmutableSet()))
|
||||
.containsExactly(fooEntity, barEntity);
|
||||
List<CommitLogManifest> manifests = auditedOfy().load().type(CommitLogManifest.class).list();
|
||||
manifests.sort(Comparator.comparing(CommitLogManifest::getCommitTime));
|
||||
assertThat(manifests.get(0).getDeletions()).isEmpty();
|
||||
assertThat(manifests.get(1).getDeletions()).containsExactly(Key.create(barEntity));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSerialization() throws Exception {
|
||||
Transaction txn = new Transaction.Builder().addUpdate(barEntity).build();
|
||||
txn.writeToDatastore();
|
||||
|
||||
txn = new Transaction.Builder().addUpdate(fooEntity).addDelete(barEntity.key()).build();
|
||||
txn = Transaction.deserialize(txn.serialize());
|
||||
|
||||
txn.writeToDatastore();
|
||||
|
||||
ofyTm()
|
||||
.transact(
|
||||
() -> {
|
||||
assertThat(ofyTm().loadByKey(fooEntity.key())).isEqualTo(fooEntity);
|
||||
assertThat(ofyTm().exists(barEntity.key())).isEqualTo(false);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDeserializationErrors() throws Exception {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream out = new ObjectOutputStream(baos);
|
||||
out.writeInt(12345);
|
||||
out.close();
|
||||
assertThrows(IllegalArgumentException.class, () -> Transaction.deserialize(baos.toByteArray()));
|
||||
|
||||
// Test with a short byte array.
|
||||
assertThrows(
|
||||
StreamCorruptedException.class, () -> Transaction.deserialize(new byte[] {1, 2, 3, 4}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTransactionSerialization() throws IOException {
|
||||
DatabaseHelper.setMigrationScheduleToSqlPrimary(fakeClock);
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
jpaTm().insert(fooEntity);
|
||||
jpaTm().insert(barEntity);
|
||||
});
|
||||
TransactionEntity txnEnt =
|
||||
jpaTm().transact(() -> jpaTm().loadByKey(VKey.createSql(TransactionEntity.class, 1L)));
|
||||
Transaction txn = Transaction.deserialize(txnEnt.getContents());
|
||||
txn.writeToDatastore();
|
||||
ofyTm()
|
||||
.transact(
|
||||
() -> {
|
||||
assertThat(ofyTm().loadByKey(fooEntity.key())).isEqualTo(fooEntity);
|
||||
assertThat(ofyTm().loadByKey(barEntity.key())).isEqualTo(barEntity);
|
||||
});
|
||||
|
||||
// Verify that no transaction was persisted for the load transaction.
|
||||
assertThat(
|
||||
jpaTm().transact(() -> jpaTm().exists(VKey.createSql(TransactionEntity.class, 2L))))
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTransactionSerializationDisabledByDefault() {
|
||||
jpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
jpaTm().insert(fooEntity);
|
||||
jpaTm().insert(barEntity);
|
||||
});
|
||||
assertThat(jpaTm().transact(() -> jpaTm().exists(VKey.createSql(TransactionEntity.class, 1L))))
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Entity(name = "TxnTestEntity")
|
||||
@javax.persistence.Entity(name = "TestEntity")
|
||||
private static class TestEntity extends ImmutableObject {
|
||||
@Id @javax.persistence.Id private String name;
|
||||
|
||||
private TestEntity() {}
|
||||
|
||||
private TestEntity(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public VKey<TestEntity> key() {
|
||||
return VKey.create(TestEntity.class, name, Key.create(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,6 +56,7 @@ import google.registry.testing.FakeKeyringModule;
|
||||
import google.registry.testing.FakeLockHandler;
|
||||
import google.registry.testing.FakeResponse;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import google.registry.testing.mapreduce.MapreduceTestCase;
|
||||
import google.registry.tldconfig.idn.IdnTableEnum;
|
||||
import google.registry.xjc.XjcXmlTransformer;
|
||||
@@ -84,12 +85,17 @@ import org.joda.time.DateTimeConstants;
|
||||
import org.joda.time.Duration;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link RdeStagingAction} in Datastore. */
|
||||
public class RdeStagingActionDatastoreTest extends MapreduceTestCase<RdeStagingAction> {
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withOfy();
|
||||
|
||||
private static final BlobId XML_FILE =
|
||||
BlobId.of("rde-bucket", "lol_2000-01-01_full_S1_R0.xml.ghostryde");
|
||||
private static final BlobId LENGTH_FILE =
|
||||
|
||||
@@ -27,10 +27,12 @@ import com.google.common.collect.ImmutableSetMultimap;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.Registrar.State;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import google.registry.xml.ValidationMode;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
@@ -53,6 +55,10 @@ class RdeStagingMapperTest {
|
||||
private ArgumentCaptor<DepositFragment> depositFragmentCaptor =
|
||||
ArgumentCaptor.forClass(DepositFragment.class);
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withOfy();
|
||||
|
||||
@RegisterExtension
|
||||
AppEngineExtension appEngineExtension =
|
||||
AppEngineExtension.builder().withDatastoreAndCloudSql().build();
|
||||
|
||||
@@ -43,6 +43,7 @@ import google.registry.testing.CloudTasksHelper;
|
||||
import google.registry.testing.CloudTasksHelper.TaskMatcher;
|
||||
import google.registry.testing.FakeKeyringModule;
|
||||
import google.registry.testing.FakeLockHandler;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import google.registry.xml.ValidationMode;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
@@ -52,12 +53,17 @@ import org.bouncycastle.openpgp.PGPPublicKey;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link RdeStagingReducer}. */
|
||||
class RdeStagingReducerTest {
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withOfy();
|
||||
|
||||
@RegisterExtension
|
||||
AppEngineExtension appEngineExtension =
|
||||
AppEngineExtension.builder().withDatastoreAndCloudSql().withTaskQueue().build();
|
||||
|
||||
@@ -21,13 +21,11 @@ import static google.registry.xjc.XjcXmlTransformer.marshalStrict;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.Registrar.State;
|
||||
import google.registry.model.registrar.RegistrarAddress;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.xjc.rderegistrar.XjcRdeRegistrar;
|
||||
import google.registry.xjc.rderegistrar.XjcRdeRegistrarAddrType;
|
||||
import google.registry.xjc.rderegistrar.XjcRdeRegistrarPostalInfoEnumType;
|
||||
@@ -47,11 +45,11 @@ import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
*/
|
||||
public class RegistrarToXjcConverterTest {
|
||||
|
||||
private final FakeClock clock = new FakeClock(DateTime.parse("2013-01-01T00:00:00Z"));
|
||||
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withDatastoreAndCloudSql().build();
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
AppEngineExtension.builder().withDatastoreAndCloudSql().withClock(clock).build();
|
||||
|
||||
private Registrar registrar;
|
||||
|
||||
@@ -86,9 +84,8 @@ public class RegistrarToXjcConverterTest {
|
||||
.setWhoisServer("whois.goblinmen.example")
|
||||
.setUrl("http://www.goblinmen.example")
|
||||
.build();
|
||||
FakeClock clock = new FakeClock(DateTime.parse("2013-01-01T00:00:00Z"));
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
registrar = cloneAndSetAutoTimestamps(registrar); // Set the creation time in 2013.
|
||||
registrar = registrar.asBuilder().setLastUpdateTime(null).build();
|
||||
clock.setTo(DateTime.parse("2014-01-01T00:00:00Z"));
|
||||
registrar = cloneAndSetAutoTimestamps(registrar); // Set the update time in 2014.
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import static org.mockito.Mockito.when;
|
||||
import com.google.cloud.tasks.v2.HttpMethod;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.beam.BeamActionTestBase;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule.PrimaryDatabase;
|
||||
import google.registry.reporting.ReportingModule;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.CloudTasksHelper;
|
||||
@@ -62,7 +61,6 @@ class GenerateInvoicesActionTest extends BeamActionTestBase {
|
||||
"billing_bucket",
|
||||
"REG-INV",
|
||||
true,
|
||||
PrimaryDatabase.DATASTORE,
|
||||
new YearMonth(2017, 10),
|
||||
emailUtils,
|
||||
cloudTasksUtils,
|
||||
@@ -97,7 +95,6 @@ class GenerateInvoicesActionTest extends BeamActionTestBase {
|
||||
"billing_bucket",
|
||||
"REG-INV",
|
||||
false,
|
||||
PrimaryDatabase.DATASTORE,
|
||||
new YearMonth(2017, 10),
|
||||
emailUtils,
|
||||
cloudTasksUtils,
|
||||
@@ -122,7 +119,6 @@ class GenerateInvoicesActionTest extends BeamActionTestBase {
|
||||
"billing_bucket",
|
||||
"REG-INV",
|
||||
false,
|
||||
PrimaryDatabase.DATASTORE,
|
||||
new YearMonth(2017, 10),
|
||||
emailUtils,
|
||||
cloudTasksUtils,
|
||||
|
||||
-4
@@ -22,7 +22,6 @@ import static org.mockito.Mockito.when;
|
||||
import com.google.cloud.tasks.v2.HttpMethod;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.beam.BeamActionTestBase;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule.PrimaryDatabase;
|
||||
import google.registry.reporting.ReportingModule;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.CloudTasksHelper;
|
||||
@@ -57,7 +56,6 @@ class GenerateSpec11ReportActionTest extends BeamActionTestBase {
|
||||
"gs://reporting-project/reporting-bucket/",
|
||||
"api_key/a",
|
||||
clock.nowUtc().toLocalDate(),
|
||||
PrimaryDatabase.DATASTORE,
|
||||
true,
|
||||
clock,
|
||||
response,
|
||||
@@ -81,7 +79,6 @@ class GenerateSpec11ReportActionTest extends BeamActionTestBase {
|
||||
"gs://reporting-project/reporting-bucket/",
|
||||
"api_key/a",
|
||||
clock.nowUtc().toLocalDate(),
|
||||
PrimaryDatabase.DATASTORE,
|
||||
true,
|
||||
clock,
|
||||
response,
|
||||
@@ -115,7 +112,6 @@ class GenerateSpec11ReportActionTest extends BeamActionTestBase {
|
||||
"gs://reporting-project/reporting-bucket/",
|
||||
"api_key/a",
|
||||
clock.nowUtc().toLocalDate(),
|
||||
PrimaryDatabase.DATASTORE,
|
||||
false,
|
||||
clock,
|
||||
response,
|
||||
|
||||
@@ -27,7 +27,6 @@ import google.registry.model.registrar.RegistrarContact;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationWithCoverageExtension;
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import google.registry.util.SerializeUtils;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
@@ -45,10 +44,6 @@ class RegistrarContactTest {
|
||||
JpaIntegrationWithCoverageExtension jpa =
|
||||
new JpaTestExtensions.Builder().buildIntegrationWithCoverageExtension();
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT + 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withJpa();
|
||||
|
||||
private Registrar testRegistrar;
|
||||
|
||||
private RegistrarContact testRegistrarPoc;
|
||||
|
||||
@@ -30,7 +30,6 @@ import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationWithCoverageExtension;
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
@@ -50,10 +49,6 @@ public class RegistrarDaoTest {
|
||||
JpaIntegrationWithCoverageExtension jpa =
|
||||
new JpaTestExtensions.Builder().withClock(fakeClock).buildIntegrationWithCoverageExtension();
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT + 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withJpa();
|
||||
|
||||
private final VKey<Registrar> registrarKey = VKey.createSql(Registrar.class, "registrarId");
|
||||
|
||||
private Registrar testRegistrar;
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
// Copyright 2021 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.schema.replay;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarContact;
|
||||
import google.registry.model.registrar.RegistrarContact.RegistrarPocId;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link SqlEntity#getPrimaryKeyString}. */
|
||||
public class SqlEntityTest {
|
||||
|
||||
@RegisterExtension
|
||||
@Order(1)
|
||||
final DatastoreEntityExtension datastoreEntityExtension = new DatastoreEntityExtension();
|
||||
|
||||
@RegisterExtension
|
||||
final AppEngineExtension database =
|
||||
new AppEngineExtension.Builder().withCloudSql().withoutCannedData().build();
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT + 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withJpa();
|
||||
|
||||
@BeforeEach
|
||||
void setup() throws Exception {
|
||||
AppEngineExtension.loadInitialData();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getPrimaryKeyString_oneIdColumn() {
|
||||
// AppEngineExtension canned data: Registrar1
|
||||
assertThat(
|
||||
tm().transact(() -> tm().loadByKey(Registrar.createVKey("NewRegistrar")))
|
||||
.getPrimaryKeyString())
|
||||
.contains("NewRegistrar");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getPrimaryKeyString_multiId() {
|
||||
// AppEngineExtension canned data: RegistrarContact1
|
||||
VKey<RegistrarContact> key =
|
||||
VKey.createSql(
|
||||
RegistrarContact.class, new RegistrarPocId("janedoe@theregistrar.com", "NewRegistrar"));
|
||||
String expected = "emailAddress=janedoe@theregistrar.com\n registrarId=NewRegistrar";
|
||||
assertThat(tm().transact(() -> tm().loadByKey(key)).getPrimaryKeyString()).contains(expected);
|
||||
}
|
||||
}
|
||||
@@ -71,8 +71,6 @@ import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.billing.BillingEvent.Flag;
|
||||
import google.registry.model.billing.BillingEvent.Reason;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState;
|
||||
import google.registry.model.contact.ContactAuthInfo;
|
||||
import google.registry.model.contact.ContactHistory;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
@@ -126,7 +124,6 @@ import org.joda.money.CurrencyUnit;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/** Static utils for setting up test resources. */
|
||||
public class DatabaseHelper {
|
||||
@@ -1210,7 +1207,7 @@ public class DatabaseHelper {
|
||||
* entities.
|
||||
*/
|
||||
public static <R> void insertSimpleResources(final Iterable<R> resources) {
|
||||
tm().transact(() -> tm().insertAllWithoutBackup(ImmutableList.copyOf(resources)));
|
||||
tm().transact(() -> tm().putAllWithoutBackup(ImmutableList.copyOf(resources)));
|
||||
maybeAdvanceClock();
|
||||
// Force the session to be cleared so that when we read it back, we read from Datastore
|
||||
// and not from the transaction's session cache.
|
||||
@@ -1226,18 +1223,10 @@ public class DatabaseHelper {
|
||||
|
||||
/** Force the create and update timestamps to get written into the resource. */
|
||||
public static <R> R cloneAndSetAutoTimestamps(final R resource) {
|
||||
R result;
|
||||
if (tm().isOfy()) {
|
||||
result =
|
||||
tm().transact(
|
||||
() -> auditedOfy().load().fromEntity(auditedOfy().save().toEntity(resource)));
|
||||
} else {
|
||||
// We have to separate the read and write operation into different transactions
|
||||
// otherwise JPA would just return the input entity instead of actually creating a
|
||||
// clone.
|
||||
tm().transact(() -> tm().put(resource));
|
||||
result = tm().transact(() -> tm().loadByEntity(resource));
|
||||
}
|
||||
// We have to separate the read and write operation into different transactions otherwise JPA
|
||||
// would just return the input entity instead of actually creating a clone.
|
||||
tm().transact(() -> tm().put(resource));
|
||||
R result = tm().transact(() -> tm().loadByEntity(resource));
|
||||
maybeAdvanceClock();
|
||||
return result;
|
||||
}
|
||||
@@ -1408,104 +1397,5 @@ public class DatabaseHelper {
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a DATASTORE_PRIMARY_NO_ASYNC state on the {@link DatabaseMigrationStateSchedule}.
|
||||
*
|
||||
* <p>In order to allow for tests to manipulate the clock how they need, we start the transitions
|
||||
* one millisecond after the clock's current time (in case the clock's current value is
|
||||
* START_OF_TIME). We then advance the clock one second so that we're in the
|
||||
* DATASTORE_PRIMARY_READ_ONLY phase.
|
||||
*
|
||||
* <p>We must use the current time, otherwise the setting of the migration state will fail due to
|
||||
* an invalid transition.
|
||||
*/
|
||||
public static void setMigrationScheduleToDatastorePrimaryNoAsync(FakeClock fakeClock) {
|
||||
DateTime now = fakeClock.nowUtc();
|
||||
jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
DatabaseMigrationStateSchedule.set(
|
||||
ImmutableSortedMap.of(
|
||||
START_OF_TIME,
|
||||
MigrationState.DATASTORE_ONLY,
|
||||
now.plusMillis(1),
|
||||
MigrationState.DATASTORE_PRIMARY,
|
||||
now.plusMillis(2),
|
||||
MigrationState.DATASTORE_PRIMARY_NO_ASYNC)));
|
||||
fakeClock.advanceBy(Duration.standardSeconds(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a DATASTORE_PRIMARY_READ_ONLY state on the {@link DatabaseMigrationStateSchedule}.
|
||||
*
|
||||
* <p>In order to allow for tests to manipulate the clock how they need, we start the transitions
|
||||
* one millisecond after the clock's current time (in case the clock's current value is
|
||||
* START_OF_TIME). We then advance the clock one second so that we're in the
|
||||
* DATASTORE_PRIMARY_READ_ONLY phase.
|
||||
*
|
||||
* <p>We must use the current time, otherwise the setting of the migration state will fail due to
|
||||
* an invalid transition.
|
||||
*/
|
||||
public static void setMigrationScheduleToDatastorePrimaryReadOnly(FakeClock fakeClock) {
|
||||
DateTime now = fakeClock.nowUtc();
|
||||
jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
DatabaseMigrationStateSchedule.set(
|
||||
ImmutableSortedMap.of(
|
||||
START_OF_TIME,
|
||||
MigrationState.DATASTORE_ONLY,
|
||||
now.plusMillis(1),
|
||||
MigrationState.DATASTORE_PRIMARY,
|
||||
now.plusMillis(2),
|
||||
MigrationState.DATASTORE_PRIMARY_NO_ASYNC,
|
||||
now.plusMillis(3),
|
||||
MigrationState.DATASTORE_PRIMARY_READ_ONLY)));
|
||||
fakeClock.advanceBy(Duration.standardSeconds(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a SQL_PRIMARY state on the {@link DatabaseMigrationStateSchedule}.
|
||||
*
|
||||
* <p>In order to allow for tests to manipulate the clock how they need, we start the transitions
|
||||
* one millisecond after the clock's current time (in case the clock's current value is
|
||||
* START_OF_TIME). We then advance the clock one second so that we're in the SQL_PRIMARY phase.
|
||||
*
|
||||
* <p>We must use the current time, otherwise the setting of the migration state will fail due to
|
||||
* an invalid transition.
|
||||
*/
|
||||
public static void setMigrationScheduleToSqlPrimary(FakeClock fakeClock) {
|
||||
DateTime now = fakeClock.nowUtc();
|
||||
jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
DatabaseMigrationStateSchedule.set(
|
||||
ImmutableSortedMap.of(
|
||||
START_OF_TIME,
|
||||
MigrationState.DATASTORE_ONLY,
|
||||
now.plusMillis(1),
|
||||
MigrationState.DATASTORE_PRIMARY,
|
||||
now.plusMillis(2),
|
||||
MigrationState.DATASTORE_PRIMARY_NO_ASYNC,
|
||||
now.plusMillis(3),
|
||||
MigrationState.DATASTORE_PRIMARY_READ_ONLY,
|
||||
now.plusMillis(4),
|
||||
MigrationState.SQL_PRIMARY)));
|
||||
fakeClock.advanceBy(Duration.standardSeconds(1));
|
||||
}
|
||||
|
||||
/** Removes the database migration schedule, in essence transitioning to DATASTORE_ONLY. */
|
||||
public static void removeDatabaseMigrationSchedule() {
|
||||
// use the raw calls because going SQL_PRIMARY -> DATASTORE_ONLY is not valid
|
||||
jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.putIgnoringReadOnlyWithoutBackup(
|
||||
new DatabaseMigrationStateSchedule(
|
||||
DatabaseMigrationStateSchedule.DEFAULT_TRANSITION_MAP)));
|
||||
DatabaseMigrationStateSchedule.CACHE.invalidateAll();
|
||||
}
|
||||
|
||||
private DatabaseHelper() {}
|
||||
}
|
||||
|
||||
@@ -23,16 +23,13 @@ import com.googlecode.objectify.annotation.Parent;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.VirtualEntity;
|
||||
import google.registry.model.common.EntityGroupRoot;
|
||||
import google.registry.model.replay.DatastoreAndSqlEntity;
|
||||
import google.registry.model.replay.EntityTest.EntityForTesting;
|
||||
import google.registry.persistence.VKey;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
/** A test model object that can be persisted in any entity group. */
|
||||
@Entity
|
||||
@javax.persistence.Entity
|
||||
@EntityForTesting
|
||||
public class TestObject extends ImmutableObject implements DatastoreAndSqlEntity {
|
||||
public class TestObject extends ImmutableObject {
|
||||
|
||||
@Parent @Transient Key<EntityGroupRoot> parent;
|
||||
|
||||
@@ -75,7 +72,6 @@ public class TestObject extends ImmutableObject implements DatastoreAndSqlEntity
|
||||
/** A test @VirtualEntity model object, which should not be persisted. */
|
||||
@Entity
|
||||
@VirtualEntity
|
||||
@EntityForTesting
|
||||
public static class TestVirtualObject extends ImmutableObject {
|
||||
|
||||
@Id String id;
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
|
||||
package google.registry.testing;
|
||||
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.ofyTm;
|
||||
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.persistence.transaction.TransactionManager;
|
||||
import google.registry.persistence.transaction.TransactionManagerFactory;
|
||||
import org.junit.jupiter.api.extension.AfterEachCallback;
|
||||
@@ -35,35 +35,17 @@ import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
* <p>This extension is incompatible with {@link DualDatabaseTest}. Use either that or this, but not
|
||||
* both.
|
||||
*/
|
||||
@DeleteAfterMigration
|
||||
public final class TmOverrideExtension implements BeforeEachCallback, AfterEachCallback {
|
||||
|
||||
private static enum TmOverride {
|
||||
OFY,
|
||||
JPA;
|
||||
}
|
||||
|
||||
private final TmOverride tmOverride;
|
||||
|
||||
private TmOverrideExtension(TmOverride tmOverride) {
|
||||
this.tmOverride = tmOverride;
|
||||
}
|
||||
|
||||
/** Use the {@link google.registry.model.ofy.DatastoreTransactionManager} for all tests. */
|
||||
public static TmOverrideExtension withOfy() {
|
||||
return new TmOverrideExtension(TmOverride.OFY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the {@link google.registry.persistence.transaction.JpaTransactionManager} for all tests.
|
||||
*/
|
||||
public static TmOverrideExtension withJpa() {
|
||||
return new TmOverrideExtension(TmOverride.JPA);
|
||||
return new TmOverrideExtension();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeEach(ExtensionContext context) {
|
||||
TransactionManagerFactory.setTmOverrideForTest(
|
||||
tmOverride == TmOverride.OFY ? ofyTm() : jpaTm());
|
||||
TransactionManagerFactory.setTmOverrideForTest(ofyTm());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -89,13 +89,18 @@ class NordnUploadActionTest {
|
||||
|
||||
private static final String LOCATION_URL = "http://trololol";
|
||||
|
||||
private final FakeClock clock = new FakeClock(DateTime.parse("2010-05-01T10:11:12Z"));
|
||||
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withDatastoreAndCloudSql().withTaskQueue().build();
|
||||
AppEngineExtension.builder()
|
||||
.withDatastoreAndCloudSql()
|
||||
.withClock(clock)
|
||||
.withTaskQueue()
|
||||
.build();
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
private final FakeClock clock = new FakeClock(DateTime.parse("2010-05-01T10:11:12Z"));
|
||||
|
||||
private final LordnRequestInitializer lordnRequestInitializer =
|
||||
new LordnRequestInitializer(Optional.of("attack"));
|
||||
private final NordnUploadAction action = new NordnUploadAction();
|
||||
|
||||
@@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.common.io.Resources;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import google.registry.tools.EntityWrapper.Property;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@@ -32,6 +33,7 @@ import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
@DeleteAfterMigration
|
||||
public class CompareDbBackupsTest {
|
||||
|
||||
private static final int BASE_ID = 1001;
|
||||
|
||||
@@ -55,9 +55,9 @@ class CreateTldCommandTest extends CommandTestCase<CreateTldCommand> {
|
||||
|
||||
@Test
|
||||
void testSuccess() throws Exception {
|
||||
DateTime before = DateTime.now(UTC);
|
||||
DateTime before = fakeClock.nowUtc();
|
||||
runCommandForced("xn--q9jyb4c", "--roid_suffix=Q9JYB4C", "--dns_writers=FooDnsWriter");
|
||||
DateTime after = DateTime.now(UTC);
|
||||
DateTime after = fakeClock.nowUtc();
|
||||
|
||||
Registry registry = Registry.get("xn--q9jyb4c");
|
||||
assertThat(registry).isNotNull();
|
||||
|
||||
-151
@@ -1,151 +0,0 @@
|
||||
// Copyright 2020 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.tools;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.loadAllOf;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveDomain;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.joda.money.CurrencyUnit.USD;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.billing.BillingEvent.Reason;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.Period;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.transfer.DomainTransferData;
|
||||
import org.joda.money.Money;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link DedupeOneTimeBillingEventIdsCommand}.
|
||||
*
|
||||
* <p>Note that these are _not_ dual database tests even though the action has been converted. The
|
||||
* dedupe was strictly a one-time event that needed to be done prior to moving to SQL. It should no
|
||||
* longer be necessary and we may want to simply remove the command.
|
||||
*/
|
||||
class DedupeOneTimeBillingEventIdsCommandTest
|
||||
extends CommandTestCase<DedupeOneTimeBillingEventIdsCommand> {
|
||||
|
||||
DomainBase domain;
|
||||
DomainHistory historyEntry;
|
||||
PollMessage.Autorenew autorenewToResave;
|
||||
BillingEvent.OneTime billingEventToResave;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
createTld("foobar");
|
||||
domain = persistActiveDomain("foo.foobar");
|
||||
historyEntry = persistHistoryEntry(domain);
|
||||
autorenewToResave = persistAutorenewPollMessage(historyEntry);
|
||||
billingEventToResave = persistBillingEvent(historyEntry);
|
||||
}
|
||||
|
||||
@Test
|
||||
void resaveBillingEvent_succeeds() throws Exception {
|
||||
runCommand(
|
||||
"--force",
|
||||
"--key_paths_file",
|
||||
writeToNamedTmpFile("keypath.txt", getKeyPathLiteral(billingEventToResave)));
|
||||
|
||||
int count = 0;
|
||||
for (BillingEvent.OneTime billingEvent : loadAllOf(BillingEvent.OneTime.class)) {
|
||||
count++;
|
||||
assertThat(billingEvent.getId()).isNotEqualTo(billingEventToResave.getId());
|
||||
assertThat(billingEvent.asBuilder().setId(billingEventToResave.getId()).build())
|
||||
.isEqualTo(billingEventToResave);
|
||||
}
|
||||
assertThat(count).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void resaveBillingEvent_failsWhenReferredByDomain() {
|
||||
persistResource(
|
||||
domain
|
||||
.asBuilder()
|
||||
.setTransferData(
|
||||
new DomainTransferData.Builder()
|
||||
.setServerApproveEntities(ImmutableSet.of(billingEventToResave.createVKey()))
|
||||
.build())
|
||||
.build());
|
||||
|
||||
assertThrows(
|
||||
IllegalStateException.class,
|
||||
() ->
|
||||
runCommand(
|
||||
"--force",
|
||||
"--key_paths_file",
|
||||
writeToNamedTmpFile("keypath.txt", getKeyPathLiteral(billingEventToResave))));
|
||||
}
|
||||
|
||||
private PollMessage.Autorenew persistAutorenewPollMessage(HistoryEntry historyEntry) {
|
||||
return persistResource(
|
||||
new PollMessage.Autorenew.Builder()
|
||||
.setRegistrarId("TheRegistrar")
|
||||
.setEventTime(fakeClock.nowUtc())
|
||||
.setMsg("Test poll message")
|
||||
.setParent(historyEntry)
|
||||
.setAutorenewEndTime(fakeClock.nowUtc().plusDays(365))
|
||||
.setTargetId("foobar.foo")
|
||||
.build());
|
||||
}
|
||||
|
||||
private BillingEvent.OneTime persistBillingEvent(DomainHistory historyEntry) {
|
||||
return persistResource(
|
||||
new BillingEvent.OneTime.Builder()
|
||||
.setRegistrarId("a registrar")
|
||||
.setTargetId("foo.tld")
|
||||
.setParent(historyEntry)
|
||||
.setReason(Reason.CREATE)
|
||||
.setFlags(ImmutableSet.of(BillingEvent.Flag.ANCHOR_TENANT))
|
||||
.setPeriodYears(2)
|
||||
.setCost(Money.of(USD, 1))
|
||||
.setEventTime(fakeClock.nowUtc())
|
||||
.setBillingTime(fakeClock.nowUtc().plusDays(5))
|
||||
.build());
|
||||
}
|
||||
|
||||
private DomainHistory persistHistoryEntry(DomainBase parent) {
|
||||
return persistResource(
|
||||
new DomainHistory.Builder()
|
||||
.setDomain(parent)
|
||||
.setType(HistoryEntry.Type.DOMAIN_CREATE)
|
||||
.setPeriod(Period.create(1, Period.Unit.YEARS))
|
||||
.setXmlBytes("<xml></xml>".getBytes(UTF_8))
|
||||
.setModificationTime(fakeClock.nowUtc())
|
||||
.setRegistrarId("foo")
|
||||
.setTrid(Trid.create("ABC-123", "server-trid"))
|
||||
.setBySuperuser(false)
|
||||
.setReason("reason")
|
||||
.setRequestedByRegistrar(false)
|
||||
.build());
|
||||
}
|
||||
|
||||
private static String getKeyPathLiteral(Object entity) {
|
||||
Key<?> key = Key.create(entity);
|
||||
return String.format(
|
||||
"\"DomainBase\", \"%s\", \"HistoryEntry\", %s, \"%s\", %s",
|
||||
key.getParent().getParent().getName(), key.getParent().getId(), key.getKind(), key.getId());
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
// Copyright 2021 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.tools;
|
||||
|
||||
import static google.registry.model.common.DatabaseMigrationStateSchedule.DEFAULT_TRANSITION_MAP;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
|
||||
/** Tests for {@link GetDatabaseMigrationStateCommand}. */
|
||||
@DualDatabaseTest
|
||||
public class GetDatabaseMigrationStateCommandTest
|
||||
extends CommandTestCase<GetDatabaseMigrationStateCommand> {
|
||||
|
||||
@AfterEach
|
||||
void afterEach() {
|
||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testInitial_returnsDatastoreOnly() throws Exception {
|
||||
runCommand();
|
||||
assertStdoutIs(
|
||||
String.format("Current migration schedule: %s\n", DEFAULT_TRANSITION_MAP.toValueMap()));
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testFullSchedule() throws Exception {
|
||||
DateTime now = fakeClock.nowUtc();
|
||||
ImmutableSortedMap<DateTime, MigrationState> transitions =
|
||||
ImmutableSortedMap.of(
|
||||
START_OF_TIME,
|
||||
MigrationState.DATASTORE_ONLY,
|
||||
now.plusHours(1),
|
||||
MigrationState.DATASTORE_PRIMARY,
|
||||
now.plusHours(2),
|
||||
MigrationState.DATASTORE_PRIMARY_NO_ASYNC,
|
||||
now.plusHours(3),
|
||||
MigrationState.DATASTORE_PRIMARY_READ_ONLY,
|
||||
now.plusHours(4),
|
||||
MigrationState.SQL_PRIMARY,
|
||||
now.plusHours(5),
|
||||
MigrationState.SQL_ONLY);
|
||||
jpaTm().transact(() -> DatabaseMigrationStateSchedule.set(transitions));
|
||||
runCommand();
|
||||
assertStdoutIs(String.format("Current migration schedule: %s\n", transitions));
|
||||
}
|
||||
}
|
||||
@@ -19,19 +19,15 @@ import static google.registry.testing.DatabaseHelper.newDomainBase;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveDomain;
|
||||
import static google.registry.testing.DatabaseHelper.persistDeletedDomain;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.beust.jcommander.ParameterException;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link GetDomainCommand}. */
|
||||
class GetDomainCommandTest extends CommandTestCase<GetDomainCommand> {
|
||||
|
||||
private DateTime now = DateTime.now(UTC);
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
createTld("tld");
|
||||
@@ -55,7 +51,7 @@ class GetDomainCommandTest extends CommandTestCase<GetDomainCommand> {
|
||||
persistActiveDomain("example.tld");
|
||||
runCommand("example.tld", "--expand");
|
||||
assertInStdout("fullyQualifiedDomainName=example.tld");
|
||||
assertInStdout("contactId=contact1234");
|
||||
assertInStdout("contact=Key<?>(ContactResource(\"3-ROID\"))");
|
||||
assertInStdout(
|
||||
"Websafe key: "
|
||||
+ "kind:DomainBase"
|
||||
@@ -70,7 +66,7 @@ class GetDomainCommandTest extends CommandTestCase<GetDomainCommand> {
|
||||
persistActiveDomain("xn--aualito-txac.xn--q9jyb4c");
|
||||
runCommand("çauçalito.みんな", "--expand");
|
||||
assertInStdout("fullyQualifiedDomainName=xn--aualito-txac.xn--q9jyb4c");
|
||||
assertInStdout("contactId=contact1234");
|
||||
assertInStdout("contact=Key<?>(ContactResource(\"4-ROID\"))");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -94,15 +90,18 @@ class GetDomainCommandTest extends CommandTestCase<GetDomainCommand> {
|
||||
|
||||
@Test
|
||||
void testSuccess_domainDeletedInFuture() throws Exception {
|
||||
persistResource(newDomainBase("example.tld").asBuilder()
|
||||
.setDeletionTime(now.plusDays(1)).build());
|
||||
runCommand("example.tld", "--read_timestamp=" + now.plusMonths(1));
|
||||
persistResource(
|
||||
newDomainBase("example.tld")
|
||||
.asBuilder()
|
||||
.setDeletionTime(fakeClock.nowUtc().plusDays(1))
|
||||
.build());
|
||||
runCommand("example.tld", "--read_timestamp=" + fakeClock.nowUtc().plusMonths(1));
|
||||
assertInStdout("Domain 'example.tld' does not exist or is deleted");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_deletedDomain() throws Exception {
|
||||
persistDeletedDomain("example.tld", now.minusDays(1));
|
||||
persistDeletedDomain("example.tld", fakeClock.nowUtc().minusDays(1));
|
||||
runCommand("example.tld");
|
||||
assertInStdout("Domain 'example.tld' does not exist or is deleted");
|
||||
}
|
||||
|
||||
@@ -26,13 +26,20 @@ import static org.joda.time.DateTimeZone.UTC;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.beust.jcommander.ParameterException;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link GetResourceByKeyCommand}. */
|
||||
class GetResourceByKeyCommandTest extends CommandTestCase<GetResourceByKeyCommand> {
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withOfy();
|
||||
|
||||
private DateTime now = DateTime.now(UTC);
|
||||
|
||||
@BeforeEach
|
||||
|
||||
@@ -20,6 +20,7 @@ import static google.registry.tools.LevelDbLogReader.HEADER_SIZE;
|
||||
import com.google.appengine.api.datastore.Entity;
|
||||
import com.google.appengine.api.datastore.EntityTranslator;
|
||||
import com.google.storage.onestore.v3.OnestoreEntity.EntityProto;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.tools.LevelDbLogReader.ChunkType;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
@@ -27,6 +28,7 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/** Utility class for building a leveldb logfile. */
|
||||
@DeleteAfterMigration
|
||||
public final class LevelDbFileBuilder {
|
||||
|
||||
private final FileOutputStream out;
|
||||
|
||||
@@ -25,10 +25,12 @@ import com.google.storage.onestore.v3.OnestoreEntity.EntityProto;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import google.registry.tools.EntityWrapper.Property;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
@@ -40,6 +42,10 @@ public class LevelDbFileBuilderTest {
|
||||
|
||||
@TempDir Path tmpDir;
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withOfy();
|
||||
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withDatastoreAndCloudSql().build();
|
||||
|
||||
@@ -19,6 +19,7 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.deleteResource;
|
||||
import static google.registry.testing.DatabaseHelper.existsInDb;
|
||||
import static google.registry.testing.DatabaseHelper.loadByEntity;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveHost;
|
||||
import static google.registry.testing.DatabaseHelper.persistNewRegistrar;
|
||||
@@ -181,10 +182,10 @@ public class MutatingCommandTest {
|
||||
+ registrar2 + "\n");
|
||||
String results = command.execute();
|
||||
assertThat(results).isEqualTo("Updated 4 entities.\n");
|
||||
assertThat(loadByEntity(host1)).isNull();
|
||||
assertThat(loadByEntity(host2)).isNull();
|
||||
assertThat(loadByEntity(registrar1)).isNull();
|
||||
assertThat(loadByEntity(registrar2)).isNull();
|
||||
assertThat(existsInDb(host1)).isFalse();
|
||||
assertThat(existsInDb(host2)).isFalse();
|
||||
assertThat(existsInDb(registrar1)).isFalse();
|
||||
assertThat(existsInDb(registrar2)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -241,9 +242,9 @@ public class MutatingCommandTest {
|
||||
+ "blockPremiumNames: false -> true\n");
|
||||
String results = command.execute();
|
||||
assertThat(results).isEqualTo("Updated 4 entities.\n");
|
||||
assertThat(loadByEntity(host1)).isNull();
|
||||
assertThat(existsInDb(host1)).isFalse();
|
||||
assertThat(loadByEntity(host2)).isEqualTo(newHost2);
|
||||
assertThat(loadByEntity(registrar1)).isNull();
|
||||
assertThat(existsInDb(registrar1)).isFalse();
|
||||
assertThat(loadByEntity(registrar2)).isEqualTo(newRegistrar2);
|
||||
}
|
||||
|
||||
@@ -282,7 +283,7 @@ public class MutatingCommandTest {
|
||||
|
||||
IllegalStateException thrown = assertThrows(IllegalStateException.class, command::execute);
|
||||
assertThat(thrown).hasMessageThat().contains("Entity changed since init() was called.");
|
||||
assertThat(loadByEntity(host1)).isNull();
|
||||
assertThat(existsInDb(host1)).isFalse();
|
||||
assertThat(loadByEntity(host2)).isEqualTo(newHost2);
|
||||
// These two shouldn't've changed.
|
||||
assertThat(loadByEntity(registrar1)).isEqualTo(registrar1);
|
||||
|
||||
@@ -23,6 +23,7 @@ import static google.registry.testing.DatabaseHelper.loadRegistrar;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static google.registry.testing.DatabaseHelper.persistSimpleResource;
|
||||
import static google.registry.testing.DatabaseHelper.persistSimpleResources;
|
||||
import static google.registry.testing.DatabaseHelper.putInDb;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@@ -334,8 +335,7 @@ class RegistrarContactCommandTest extends CommandTestCase<RegistrarContactComman
|
||||
@Test
|
||||
void testDelete_failsOnDomainWhoisAbuseContact() {
|
||||
RegistrarContact registrarContact = loadRegistrar("NewRegistrar").getContacts().asList().get(0);
|
||||
persistSimpleResource(
|
||||
registrarContact.asBuilder().setVisibleInDomainWhoisAsAbuse(true).build());
|
||||
putInDb(registrarContact.asBuilder().setVisibleInDomainWhoisAsAbuse(true).build());
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
|
||||
@@ -31,12 +31,20 @@ import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit test for {@link RemoveRegistryOneKeyCommand}. */
|
||||
public class RemoveRegistryOneKeyCommandTest extends CommandTestCase<RemoveRegistryOneKeyCommand> {
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withOfy();
|
||||
|
||||
DomainBase domain;
|
||||
HistoryEntry historyEntry;
|
||||
|
||||
|
||||
@@ -25,29 +25,20 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import com.beust.jcommander.ParameterException;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.util.Clock;
|
||||
import java.util.List;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.testcontainers.shaded.com.google.common.collect.ImmutableList;
|
||||
|
||||
/** Unit tests for {@link RenewDomainCommand}. */
|
||||
public class RenewDomainCommandTest extends EppToolCommandTestCase<RenewDomainCommand> {
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
private final Clock clock = new FakeClock(DateTime.parse("2015-04-05T05:05:05Z"));
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
command.clock = clock;
|
||||
fakeClock.setTo(DateTime.parse("2015-04-05T05:05:05Z"));
|
||||
command.clock = fakeClock;
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -25,11 +25,18 @@ import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.ofy.CommitLogManifest;
|
||||
import google.registry.model.ofy.CommitLogMutation;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link ResaveEntitiesCommand}. */
|
||||
class ResaveEntitiesCommandTest extends CommandTestCase<ResaveEntitiesCommand> {
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withOfy();
|
||||
|
||||
@Test
|
||||
void testSuccess_createsCommitLogs() throws Exception {
|
||||
ContactResource contact1 = persistActiveContact("contact1");
|
||||
|
||||
@@ -28,12 +28,19 @@ import google.registry.model.ofy.CommitLogMutation;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarContact;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link ResaveEnvironmentEntitiesCommand}. */
|
||||
class ResaveEnvironmentEntitiesCommandTest
|
||||
extends CommandTestCase<ResaveEnvironmentEntitiesCommand> {
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withOfy();
|
||||
|
||||
@Test
|
||||
void testSuccess_noop() throws Exception {
|
||||
// Get rid of all the entities that this command runs on so that it does nothing.
|
||||
|
||||
@@ -22,11 +22,18 @@ import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.ofy.CommitLogManifest;
|
||||
import google.registry.model.ofy.CommitLogMutation;
|
||||
import google.registry.testing.TmOverrideExtension;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link ResaveEppResourceCommand}. */
|
||||
class ResaveEppResourcesCommandTest extends CommandTestCase<ResaveEppResourceCommand> {
|
||||
|
||||
@RegisterExtension
|
||||
@Order(Order.DEFAULT - 1)
|
||||
TmOverrideExtension tmOverrideExtension = TmOverrideExtension.withOfy();
|
||||
|
||||
@Test
|
||||
void testSuccess_createsCommitLogs() throws Exception {
|
||||
ContactResource contact = persistActiveContact("contact");
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user