mirror of
https://github.com/google/nomulus.git
synced 2025-06-27 14:54:51 +02:00
mv com/google/domain/registry google/registry
This change renames directories in preparation for the great package rename. The repository is now in a broken state because the code itself hasn't been updated. However this should ensure that git correctly preserves history for each file.
This commit is contained in:
parent
a41677aea1
commit
5012893c1d
2396 changed files with 0 additions and 0 deletions
189
javatests/google/registry/model/EntityTestCase.java
Normal file
189
javatests/google/registry/model/EntityTestCase.java
Normal file
|
@ -0,0 +1,189 @@
|
|||
// Copyright 2016 The Domain Registry 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 com.google.domain.registry.model;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth.assertWithMessage;
|
||||
import static com.google.common.truth.Truth.assert_;
|
||||
import static com.google.domain.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.domain.registry.model.ofy.Ofy;
|
||||
import com.google.domain.registry.testing.AppEngineRule;
|
||||
import com.google.domain.registry.testing.FakeClock;
|
||||
import com.google.domain.registry.testing.InjectRule;
|
||||
import com.google.domain.registry.util.CidrAddressBlock;
|
||||
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
import com.googlecode.objectify.annotation.Serialize;
|
||||
import com.googlecode.objectify.cmd.Query;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
/** Base class of all unit tests for entities which are persisted to Datastore via Objectify. */
|
||||
@RunWith(JUnit4.class)
|
||||
public class EntityTestCase {
|
||||
|
||||
@Rule
|
||||
public final AppEngineRule appEngine = AppEngineRule.builder()
|
||||
.withDatastore()
|
||||
.build();
|
||||
|
||||
@Rule
|
||||
public InjectRule inject = new InjectRule();
|
||||
|
||||
protected FakeClock clock = new FakeClock(DateTime.now(UTC));
|
||||
|
||||
@Before
|
||||
public void injectClock() throws Exception {
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
}
|
||||
|
||||
// Helper method to find private fields including inherited ones.
|
||||
private Field getField(Class<?> clazz, String name) {
|
||||
while (clazz != Object.class) {
|
||||
try {
|
||||
return clazz.getDeclaredField(name);
|
||||
} catch (NoSuchFieldException e) {
|
||||
clazz = clazz.getSuperclass();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Verify that fields are either indexed or not, depending on the parameter. */
|
||||
private void verifyIndexingHelper(
|
||||
Object obj,
|
||||
boolean indexed,
|
||||
Collection<String> fieldPaths) throws Exception {
|
||||
outer: for (String fieldPath : fieldPaths) {
|
||||
// Walk the field path and grab the value referred to on the object using reflection.
|
||||
Object fieldValue = obj;
|
||||
for (String fieldName : fieldPath.split("\\.")) {
|
||||
if (fieldValue == null) {
|
||||
throw new RuntimeException(String.format("field '%s' not found on %s",
|
||||
fieldPath, obj.getClass().getSimpleName()));
|
||||
}
|
||||
Field field = getField(fieldValue.getClass(), fieldName);
|
||||
field.setAccessible(true);
|
||||
// Check if the field is annotated with @Id. If it is, it's always indexed. Although we
|
||||
// might want to double check that fact, it's a bad idea, because filtering on a @Id field
|
||||
// will fail if the class also contains an @Parent field.
|
||||
if (field.isAnnotationPresent(Id.class)) {
|
||||
continue outer;
|
||||
}
|
||||
fieldValue = field.get(fieldValue);
|
||||
// Check if the field is a collection. If so, take the first value from the collection,
|
||||
// since we can't query on collections themselves.
|
||||
if (fieldValue instanceof Collection<?>) {
|
||||
fieldValue = ((Collection<?>) fieldValue).iterator().next();
|
||||
}
|
||||
// Same for an array.
|
||||
if (fieldValue != null && fieldValue.getClass().isArray()) {
|
||||
fieldValue = Array.getLength(fieldValue) == 0 ? null : Array.get(fieldValue, 0);
|
||||
}
|
||||
// CidrAddressBlock objects implement the Iterable<InetAddress> interface, which makes
|
||||
// Objectify think we're querying for a list (which is not allowed unless we use the IN
|
||||
// keyword). Convert the object to a String to make sure we do a query for a single value.
|
||||
if (fieldValue instanceof CidrAddressBlock) {
|
||||
fieldValue = fieldValue.toString();
|
||||
}
|
||||
}
|
||||
try {
|
||||
// Objectify happily filters on an unindexed field, and just returns zero results.
|
||||
// Do a query for that value and verify that the expected number of results are returned.
|
||||
Query<?> query = ofy().load().type(obj.getClass());
|
||||
int results = query.filter(fieldPath, fieldValue).count();
|
||||
assertWithMessage(String.format("%s was %sindexed", fieldPath, indexed ? "not " : ""))
|
||||
.that(indexed)
|
||||
.isEqualTo(results != 0);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// If the field's type was not indexable (because it's not a supported datastore type) then
|
||||
// this error will be thrown. If we expected no indexing, that's fine. Otherwise, fail.
|
||||
if (indexed || !e.getMessage().endsWith(" is not a supported property type.")) {
|
||||
assert_().fail(String.format("%s was %sindexed", fieldPath, indexed ? "not " : ""));
|
||||
}
|
||||
} catch (IllegalStateException e) {
|
||||
assert_().fail(String.format("%s (indexed=%b): %s", fieldPath, indexed, e.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** List all field paths so we can verify that we checked everything. */
|
||||
private Set<String> getAllPotentiallyIndexedFieldPaths(Class<?> clazz) {
|
||||
Set<String> fields = Sets.newHashSet();
|
||||
for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
|
||||
for (final Field field : clazz.getDeclaredFields()) {
|
||||
// Ignore static, @Serialize, @Parent and @Ignore fields, since these are never indexed.
|
||||
if (!Modifier.isStatic(field.getModifiers())
|
||||
&& !field.isAnnotationPresent(Ignore.class)
|
||||
&& !field.isAnnotationPresent(Parent.class)
|
||||
&& !field.isAnnotationPresent(Serialize.class)) {
|
||||
Class<?> fieldClass = field.getType();
|
||||
// If the field is a collection, just pretend that it was a field of that type,
|
||||
// because verifyIndexingHelper knows how to descend into collections.
|
||||
if (Collection.class.isAssignableFrom(fieldClass)) {
|
||||
Type inner = ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];
|
||||
fieldClass = inner instanceof ParameterizedType
|
||||
? (Class<?>) ((ParameterizedType) inner).getRawType()
|
||||
: (Class<?>) inner;
|
||||
}
|
||||
// Descend into persisted ImmutableObject classes, but not anything else.
|
||||
if (ImmutableObject.class.isAssignableFrom(fieldClass)) {
|
||||
fields.addAll(FluentIterable
|
||||
.from(getAllPotentiallyIndexedFieldPaths(fieldClass))
|
||||
.transform(new Function<String, String>(){
|
||||
@Override
|
||||
public String apply(String subfield) {
|
||||
return field.getName() + "." + subfield;
|
||||
}})
|
||||
.toSet());
|
||||
} else {
|
||||
fields.add(field.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
/** Verify indexing for an entity. */
|
||||
public void verifyIndexing(Object obj, String... indexed) throws Exception {
|
||||
Set<String> indexedSet = ImmutableSet.copyOf(indexed);
|
||||
Set<String> allSet = getAllPotentiallyIndexedFieldPaths(obj.getClass());
|
||||
// Sanity test that the indexed fields we listed were found.
|
||||
assertThat(Sets.intersection(allSet, indexedSet)).containsExactlyElementsIn(indexedSet);
|
||||
verifyIndexingHelper(obj, true, indexedSet);
|
||||
verifyIndexingHelper(obj, false, Sets.difference(allSet, indexedSet));
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue