mirror of
https://github.com/google/nomulus.git
synced 2025-07-08 20:23:24 +02:00
Ensure that all relevant Keys can be converted to VKeys (#883)
* Ensure that all relevant Keys can be converted to VKeys When replaying commit logs to SQL (specifically deletes) we will need to convert Datastore Keys to SQL VKeys in order to know what (if anything) to delete. The test added to EntityTest (and the associated code changes) mean that for every relevant object we'll be able to call VKeyTranslatorFactory.createVKey(Key<?>) for all possible keys that we care about. Note that we do not care about entities that only exist in Datastore or entities that are non-replicated -- by their nature, deletes for those types of objects in Datastore are not relevant in SQL. * Responses to code review - changing comments / method names - using ModelUtils
This commit is contained in:
parent
3afcc0dcb4
commit
3b1c198c11
27 changed files with 277 additions and 312 deletions
|
@ -29,8 +29,8 @@ import google.registry.model.registrar.Registrar;
|
|||
import google.registry.persistence.transaction.JpaTestRules;
|
||||
import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationTestExtension;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import java.io.Serializable;
|
||||
|
|
|
@ -16,10 +16,16 @@ package google.registry.schema.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;
|
||||
|
@ -28,13 +34,18 @@ 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);
|
||||
|
||||
|
@ -59,6 +70,47 @@ public class EntityTest {
|
|||
}
|
||||
}
|
||||
|
||||
@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 =
|
||||
new ClassGraph().enableAnnotationInfo().whitelistPackages("google.registry").scan()) {
|
||||
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<>();
|
||||
|
@ -70,17 +122,20 @@ public class EntityTest {
|
|||
return result.build();
|
||||
}
|
||||
|
||||
private ImmutableSet<String> getClassNames(ClassInfoList classInfoList) {
|
||||
private ImmutableSet<Class<?>> getClasses(ClassInfoList classInfoList) {
|
||||
return classInfoList.stream()
|
||||
.filter(ClassInfo::isStandardClass)
|
||||
.map(ClassInfo::loadClass)
|
||||
.filter(clazz -> !clazz.isAnnotationPresent(EntityForTesting.class))
|
||||
.filter(clazz -> !clazz.isAnnotationPresent(Embed.class))
|
||||
.filter(clazz -> !NON_CONVERTED_CLASSES.contains(clazz))
|
||||
.map(Class::getName)
|
||||
.collect(toImmutableSet());
|
||||
}
|
||||
|
||||
private ImmutableSet<String> getClassNames(ClassInfoList classInfoList) {
|
||||
return getClasses(classInfoList).stream().map(Class::getName).collect(toImmutableSet());
|
||||
}
|
||||
|
||||
/** Entities that are solely used for testing, to avoid scanning them in {@link EntityTest}. */
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue