/* * * * JBoss, Home of Professional Open Source. * * Copyright 2011, Red Hat, Inc., and individual contributors * * as indicated by the @author tags. See the copyright.txt file in the * * distribution for a full listing of individual contributors. * * * * This is free software; you can redistribute it and/or modify it * * under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation; either version 2.1 of * * the License, or (at your option) any later version. * * * * This software is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this software; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * * 02110-1301 USA, or see the FSF site: http://www.fsf.org. * */ package org.jboss.test.capedwarf.datastore.test; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; import com.google.appengine.api.datastore.Entity; import com.google.appengine.api.datastore.Key; import com.google.appengine.api.datastore.PreparedQuery; import com.google.appengine.api.datastore.Query; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.Assert; import static com.google.appengine.api.datastore.Query.FilterOperator.EQUAL; import static com.google.appengine.api.datastore.Query.FilterOperator.GREATER_THAN; import static com.google.appengine.api.datastore.Query.FilterOperator.GREATER_THAN_OR_EQUAL; import static com.google.appengine.api.datastore.Query.FilterOperator.LESS_THAN; import static com.google.appengine.api.datastore.Query.FilterOperator.LESS_THAN_OR_EQUAL; import static com.google.appengine.api.datastore.Query.FilterOperator.NOT_EQUAL; import static org.junit.Assert.assertEquals; /** * @author <a href="mailto:marko.luksa@gmail.com">Marko Luksa</a> */ public abstract class QueryTestBase extends DatastoreTestBase { protected static final String TEST_ENTITY_KIND = "test"; protected static final String SINGLE_PROPERTY_NAME = "prop"; private int idSequence; @Deployment public static WebArchive getDeployment() { return getDefaultDeployment() .addAsWebInfResource("datastore-indexes.xml") .addClass(QueryTestBase.class); } protected static Date createDate(int year, int month, int day) { Calendar cal = Calendar.getInstance(); //noinspection MagicConstant cal.set(year, month - 1, day, 0, 0, 0); cal.set(Calendar.MILLISECOND, 0); return cal.getTime(); } protected void assertList(List<Entity> expected, List<Entity> actual) { Assert.assertNotNull(actual); Assert.assertEquals(expected.size(), actual.size()); for (int i = 0; i < expected.size(); i++) { Assert.assertEquals(expected.get(i), actual.get(i)); } } protected void assertSet(Set<Entity> actual, Set<Entity> expected) { assertSet(null, actual, expected); } protected void assertSet(String message, Set<Entity> actual, Set<Entity> expected) { Assert.assertNotNull(message, actual); Assert.assertEquals(message, expected.size(), actual.size()); Set<Entity> copy = new HashSet<Entity>(expected); copy.removeAll(actual); Assert.assertTrue(message, copy.size() == 0); } protected void assertSingleResult(Entity expectedEntity, Query query) { PreparedQuery preparedQuery = service.prepare(query); assertEquals("number of results", 1, preparedQuery.countEntities(withDefaults())); Entity entityFromQuery = preparedQuery.asSingleEntity(); assertEquals(expectedEntity, entityFromQuery); } protected void assertNoResults(Query query) { PreparedQuery preparedQuery = service.prepare(query); Assert.assertEquals("number of results", 0, preparedQuery.countEntities(withDefaults())); } protected TestEntityBuilder buildTestEntity() { return createEntity(TEST_ENTITY_KIND, ++idSequence); } protected TestEntityBuilder createEntity(String kind, int id) { return new TestEntityBuilder(kind, id); } protected TestEntityBuilder createEntity(String kind, Key parent) { return new TestEntityBuilder(kind, parent); } protected TestEntityBuilder createEntity(Key key) { return new TestEntityBuilder(key); } protected Entity storeTestEntityWithSingleProperty(Object value) { return buildTestEntity() .withProperty(SINGLE_PROPERTY_NAME, value) .store(); } protected Query createQuery(Query.FilterOperator operator, Object value) { return createQuery(createFilter(operator, value)); } private Query createQuery(Query.Filter filter) { return createQuery().setFilter(filter); } private Query.FilterPredicate createFilter(Query.FilterOperator operator, Object value) { return new Query.FilterPredicate(SINGLE_PROPERTY_NAME, operator, value); } protected Query createQuery() { return new Query(TEST_ENTITY_KIND); } protected Set<Entity> queryReturnsNothing() { return queryReturns(); } protected Set<Entity> queryReturns(Set<Entity> entities) { return entities; } protected Set<Entity> queryReturns(Entity... entities) { return new HashSet<Entity>(Arrays.asList(entities)); } protected List<Entity> containsResultsInOrder(Entity... entities) { return Arrays.asList(entities); } protected Set<Entity> whenFilteringBy(Query.FilterOperator operator, Object value) { return whenFilteringWith(createFilter(operator, value)); } protected Set<Entity> whenFilteringWith(Query.Filter filter) { Query query = createQuery(filter); List<Entity> results = service.prepare(query).asList(withDefaults()); return new HashSet<Entity>(results); } protected List<Entity> listReturnedWhenFilteringBy(Query.FilterOperator operator, Object value) { Query query = createQuery(operator, value); return service.prepare(query).asList(withDefaults()); } /** * Tests if querying by GREATER_THAN, GREATER_THAN_OR_EQUAL, LESS_THAN and LESS_THAN_OR_EQUAL returns * the correct results. * * @param lowValue The lowest value among the three values. * @param midValue The medium value among the three values. * @param highValue The highest value among the three values. */ protected void testInequalityQueries(Object lowValue, Object midValue, Object highValue) { // we don't store the entities in a nice order (low, then mid, then high), because that could make the test // pass if the order in which the entities were stored was used for comparing. Entity highEntity = storeTestEntityWithSingleProperty(highValue); Entity lowEntity = storeTestEntityWithSingleProperty(lowValue); Entity midEntity = storeTestEntityWithSingleProperty(midValue); Entity nullEntity = storeTestEntityWithSingleProperty(null); assertSet(whenFilteringBy(GREATER_THAN, lowValue), queryReturns(midEntity, highEntity)); assertSet(whenFilteringBy(GREATER_THAN_OR_EQUAL, midValue), queryReturns(midEntity, highEntity)); assertSet(whenFilteringBy(LESS_THAN, highValue), queryReturns(nullEntity, midEntity, lowEntity)); assertSet(whenFilteringBy(LESS_THAN_OR_EQUAL, midValue), queryReturns(nullEntity, midEntity, lowEntity)); service.delete(lowEntity.getKey()); service.delete(midEntity.getKey()); service.delete(highEntity.getKey()); service.delete(nullEntity.getKey()); } /** * Tests whether given two entities with each having a single property, whose value is either foo or bar; when * querying by EQUAL foo, the query returns foo; and when querying by NOT_EQUAL foo, the query returns bar. * * @param foo property value for first entity * @param bar property value for second entity */ protected void testEqualityQueries(Object foo, Object bar) { Entity fooEntity = storeTestEntityWithSingleProperty(foo); Entity barEntity = storeTestEntityWithSingleProperty(bar); Entity noPropertyEntity = storeTestEntityWithoutProperties(); assertSet(whenFilteringBy(EQUAL, foo), queryReturns(fooEntity)); assertSet(whenFilteringBy(NOT_EQUAL, foo), queryReturns(barEntity)); service.delete(fooEntity.getKey()); service.delete(barEntity.getKey()); service.delete(noPropertyEntity.getKey()); } private Entity storeTestEntityWithoutProperties() { return buildTestEntity().store(); } protected class TestEntityBuilder { private Entity entity; public TestEntityBuilder(String kind, int id) { entity = new Entity(kind, id); } public TestEntityBuilder(String kind, Key parent) { entity = new Entity(kind, parent); } public TestEntityBuilder(Key key) { entity = new Entity(key); } public TestEntityBuilder withProperty(String key, Object value) { entity.setProperty(key, value); return this; } public Entity store() { service.put(entity); return entity; } } }