Make TransactionManager.loadAllOf() smart w.r.t the cross-TLD entity group (#1040)

* Make TransactionManager.loadAllOf() smart w.r.t the cross-TLD entity group

The loadAllOf() method will now automatically append the cross-TLD entity group
ancestor query as necessary, iff the entity class being loaded is tagged with
the new @IsCrossTld annotation.

* Add tests
This commit is contained in:
Ben McIlwain 2021-03-25 18:55:18 -04:00 committed by GitHub
parent 3c65ad0f8a
commit 2649a9362a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 196 additions and 20 deletions

View file

@ -19,8 +19,9 @@ import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.io.Resources.getResource;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static google.registry.export.ExportConstants.getBackupKinds;
import static google.registry.export.ExportConstants.getReportingKinds;
import static google.registry.export.AnnotatedEntities.getBackupKinds;
import static google.registry.export.AnnotatedEntities.getCrossTldKinds;
import static google.registry.export.AnnotatedEntities.getReportingKinds;
import static google.registry.util.ResourceUtils.readResourceUtf8;
import com.google.common.base.Joiner;
@ -31,13 +32,15 @@ import com.google.common.collect.Streams;
import com.google.re2j.Pattern;
import org.junit.jupiter.api.Test;
/** Unit tests for {@link ExportConstants}. */
class ExportConstantsTest {
/** Unit tests for {@link AnnotatedEntities}. */
class AnnotatedEntitiesTest {
private static final String GOLDEN_BACKUP_KINDS_FILENAME = "backup_kinds.txt";
private static final String GOLDEN_REPORTING_KINDS_FILENAME = "reporting_kinds.txt";
private static final String GOLDEN_CROSSTLD_KINDS_FILENAME = "crosstld_kinds.txt";
private static final String UPDATE_INSTRUCTIONS_TEMPLATE = Joiner.on('\n').join(
"",
repeat("-", 80),
@ -50,15 +53,20 @@ class ExportConstantsTest {
"");
@Test
void testBackupKinds_matchGoldenBackupKindsFile() {
void testBackupKinds_matchGoldenFile() {
checkKindsMatchGoldenFile("backed-up", GOLDEN_BACKUP_KINDS_FILENAME, getBackupKinds());
}
@Test
void testReportingKinds_matchGoldenReportingKindsFile() {
void testReportingKinds_matchGoldenFile() {
checkKindsMatchGoldenFile("reporting", GOLDEN_REPORTING_KINDS_FILENAME, getReportingKinds());
}
@Test
void testCrossTldKinds_matchGoldenFile() {
checkKindsMatchGoldenFile("crosstld", GOLDEN_CROSSTLD_KINDS_FILENAME, getCrossTldKinds());
}
@Test
void testReportingKinds_areSubsetOfBackupKinds() {
assertThat(getBackupKinds()).containsAtLeastElementsIn(getReportingKinds());
@ -70,7 +78,7 @@ class ExportConstantsTest {
String.format(
UPDATE_INSTRUCTIONS_TEMPLATE,
kindsName,
getResource(ExportConstantsTest.class, goldenFilename).toString(),
getResource(AnnotatedEntitiesTest.class, goldenFilename).toString(),
Joiner.on('\n').join(actualKinds));
assertWithMessage(updateInstructions)
.that(actualKinds)
@ -85,7 +93,7 @@ class ExportConstantsTest {
* @return ImmutableList<String>
*/
private static ImmutableList<String> extractListFromFile(String filename) {
String fileContents = readResourceUtf8(ExportConstantsTest.class, filename);
String fileContents = readResourceUtf8(AnnotatedEntitiesTest.class, filename);
final Pattern stripComments = Pattern.compile("\\s*#.*$");
return Streams.stream(Splitter.on('\n').split(fileContents.trim()))
.map(line -> stripComments.matcher(line).replaceFirst(""))

View file

@ -54,7 +54,7 @@ public class BackupDatastoreActionTest {
action.response = response;
when(datastoreAdmin.export(
"gs://registry-project-id-datastore-backups", ExportConstants.getBackupKinds()))
"gs://registry-project-id-datastore-backups", AnnotatedEntities.getBackupKinds()))
.thenReturn(exportRequest);
when(exportRequest.execute()).thenReturn(backupOperation);
when(backupOperation.getName())
@ -73,7 +73,7 @@ public class BackupDatastoreActionTest {
.param(CHECK_BACKUP_NAME_PARAM, "projects/registry-project-id/operations/ASA1ODYwNjc")
.param(
CHECK_BACKUP_KINDS_TO_LOAD_PARAM,
Joiner.on(",").join(ExportConstants.getReportingKinds()))
Joiner.on(",").join(AnnotatedEntities.getReportingKinds()))
.method("POST"));
assertThat(response.getPayload())
.isEqualTo(

View file

@ -0,0 +1,72 @@
// 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.ofy;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
import static google.registry.persistence.transaction.TransactionManagerFactory.ofyTm;
import static google.registry.testing.DatabaseHelper.persistResources;
import com.google.common.collect.ImmutableList;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
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.schema.replay.EntityTest.EntityForTesting;
import google.registry.testing.AppEngineExtension;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link DatastoreTransactionManager}. */
public class DatastoreTransactionManagerTest {
@RegisterExtension
public final AppEngineExtension appEngine =
AppEngineExtension.builder()
.withDatastore()
.withOfyTestEntities(InCrossTldTestEntity.class)
.build();
@Test
void test_loadAllOf_usesAncestorQuery() {
InCrossTldTestEntity foo = new InCrossTldTestEntity("foo");
InCrossTldTestEntity bar = new InCrossTldTestEntity("bar");
InCrossTldTestEntity baz = new InCrossTldTestEntity("baz");
baz.parent = null;
persistResources(ImmutableList.of(foo, bar, baz));
// baz is excluded by the cross-TLD ancestor query
assertThat(ofyTm().loadAllOf(InCrossTldTestEntity.class)).containsExactly(foo, bar);
}
@Entity
@EntityForTesting
@InCrossTld
private static class InCrossTldTestEntity extends ImmutableObject {
@Id String name;
@Parent Key<EntityGroupRoot> parent = getCrossTldKey();
private InCrossTldTestEntity(String name) {
this.name = name;
}
// Needs to exist to make Objectify happy.
@SuppressWarnings("unused")
private InCrossTldTestEntity() {}
}
}

View file

@ -0,0 +1,16 @@
ClaimsListShard
ClaimsListSingleton
Cursor
DatabaseTransitionSchedule
KmsSecret
KmsSecretRevision
PremiumList
PremiumListEntry
PremiumListRevision
Registrar
RegistrarContact
Registry
ReservedList
ServerSecret
SignedMarkRevocationList
TmchCrl