/*
* $Id: BeanMixin.java 1075 2009-05-07 06:41:19Z lhoriman $
* $URL: https://subetha.googlecode.com/svn/branches/resin/rtest/src/org/subethamail/rtest/util/BeanMixin.java $
*/
package com.googlecode.objectify.test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.appengine.api.datastore.Cursor;
import com.google.appengine.api.datastore.QueryResultIterator;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.Query;
import com.googlecode.objectify.test.entity.Child;
import com.googlecode.objectify.test.entity.Employee;
import com.googlecode.objectify.test.entity.NamedTrivial;
import com.googlecode.objectify.test.entity.Trivial;
/**
* Tests of various queries
*
* @author Jeff Schnitzer <jeff@infohazard.org>
*/
public class QueryTests extends TestBase
{
/** */
@SuppressWarnings("unused")
private static Logger log = LoggerFactory.getLogger(QueryTests.class);
/** */
Trivial triv1;
Trivial triv2;
List<Key<Trivial>> keys;
/** */
@BeforeMethod
public void setUp()
{
super.setUp();
this.triv1 = new Trivial("foo1", 1);
this.triv2 = new Trivial("foo2", 2);
List<Trivial> trivs = new ArrayList<Trivial>();
trivs.add(this.triv1);
trivs.add(this.triv2);
Objectify ofy = this.fact.begin();
Map<Key<Trivial>, Trivial> result = ofy.put(trivs);
this.keys = new ArrayList<Key<Trivial>>(result.keySet());
}
/** */
@Test
public void testKeysOnly() throws Exception
{
Objectify ofy = this.fact.begin();
Query<Trivial> q = ofy.query(Trivial.class);
int count = 0;
for (Key<Trivial> k: q.fetchKeys())
{
assert keys.contains(k);
count++;
}
assert count == keys.size();
// Just for the hell of it, test the other methods
assert q.countAll() == keys.size();
q.limit(2);
for (Key<Trivial> k: q.fetchKeys())
assert keys.contains(k);
Key<Trivial> first = q.getKey();
assert first.equals(this.keys.get(0));
q.offset(1);
Key<Trivial> second = q.getKey();
assert second.equals(this.keys.get(1));
}
/** */
@Test
public void testLimitAndCursorUsingIterator() throws Exception {
// create 30 objects with someString=foo,
// then search for limit 20 (finding cursor at 15th position)
// then search for limit 20 using that cursor
// then use get() and see if we get the object at cursor
Objectify ofy = this.fact.begin();
for (int i = 0; i < 30; i++) {
ofy.put(new Trivial("foo", i));
}
Query<Trivial> q1 = ofy.query(Trivial.class).filter("someString", "foo");
q1.limit(20);
QueryResultIterator<Trivial> i1 = q1.iterator();
List<Trivial> l1 = new ArrayList<Trivial>();
Cursor cursor = null;
Trivial objectAfterCursor = null;
int count = 1;
while (i1.hasNext())
{
Trivial trivial = i1.next();
l1.add(trivial);
if (count == 15) {
cursor = i1.getCursor();
}
if (count == 16) {
objectAfterCursor = trivial;
}
count++;
}
assert l1.size() == 20;
Query<Trivial> q2 = ofy.query(Trivial.class).filter("someString =", "foo");
q2.limit(20).cursor(cursor);
QueryResultIterator<Trivial> i2 = q2.iterator();
List<Trivial> l2 = new ArrayList<Trivial>();
while (i2.hasNext())
{
Trivial trivial = i2.next();
l2.add(trivial);
}
assert l2.size() == 15;
Trivial gotten = q2.get();
assert gotten.getId().equals(objectAfterCursor.getId());
}
/** */
@Test
public void testNormalSorting() throws Exception
{
Objectify ofy = this.fact.begin();
Iterator<Trivial> it = ofy.query(Trivial.class).order("someString").iterator();
Trivial t1 = it.next();
Trivial t2 = it.next();
assert t1.getId().equals(triv1.getId());
assert t2.getId().equals(triv2.getId());
}
/** */
@Test
public void testNormalReverseSorting() throws Exception
{
Objectify ofy = this.fact.begin();
Iterator<Trivial> it = ofy.query(Trivial.class).order("-someString").iterator();
// t2 first
Trivial t2 = it.next();
Trivial t1 = it.next();
assert t1.getId().equals(triv1.getId());
assert t2.getId().equals(triv2.getId());
}
/** Unfortunately we can only test one way without custom index file */
@Test
public void testIdSorting() throws Exception
{
Objectify ofy = this.fact.begin();
Iterator<Trivial> it = ofy.query(Trivial.class).order("id").iterator();
Trivial t1 = it.next();
Trivial t2 = it.next();
assert t1.getId().equals(triv1.getId());
assert t2.getId().equals(triv2.getId());
}
/** */
@Test
public void testFiltering() throws Exception
{
Objectify ofy = this.fact.begin();
Iterator<Trivial> it = ofy.query(Trivial.class).filter("someString >", triv1.getSomeString()).iterator();
Trivial t2 = it.next();
assert !it.hasNext();
assert t2.getId().equals(triv2.getId());
}
/** */
@Test
public void testFilteringByNull() throws Exception
{
Objectify ofy = this.fact.begin();
Trivial triv3 = new Trivial(null, 3);
ofy.put(triv3);
Iterator<Trivial> it = ofy.query(Trivial.class).filter("someString", null).iterator();
assert it.hasNext();
Trivial t3 = it.next();
assert !it.hasNext();
assert t3.getId().equals(triv3.getId());
}
/** */
@Test
public void testIdFiltering() throws Exception
{
Objectify ofy = this.fact.begin();
Iterator<Trivial> it = ofy.query(Trivial.class).filter("id >", triv1.getId()).iterator();
Trivial t2 = it.next();
assert !it.hasNext();
assert t2.getId().equals(triv2.getId());
}
/** */
@Test
public void testQueryToString() throws Exception
{
Objectify ofy = this.fact.begin();
Query<Trivial> q1 = ofy.query(Trivial.class).filter("id >", triv1.getId());
Query<Trivial> q2 = ofy.query(Trivial.class).filter("id <", triv1.getId());
Query<Trivial> q3 = ofy.query(Trivial.class).filter("id >", triv1.getId()).order("-id");
assert !q1.toString().equals(q2.toString());
assert !q1.toString().equals(q3.toString());
}
/** */
@Test
public void testEmptySingleResult() throws Exception
{
Objectify ofy = this.fact.begin();
Query<Trivial> q = ofy.query(Trivial.class).filter("id", 999999); // no such entity
assert q.get() == null;
}
/** */
@Test
public void testFilteringByKeyField() throws Exception
{
Objectify ofy = this.fact.begin();
Key<Employee> bobKey = new Key<Employee>(Employee.class, "bob");
Employee fred = new Employee("fred", bobKey);
ofy.put(fred);
Iterator<Employee> it = ofy.query(Employee.class).filter("manager", bobKey).iterator();
assert it.hasNext();
Employee fetched = it.next();
assert !it.hasNext();
assert fred.getName().equals(fetched.getName());
}
/** This is expected to fail without a kind: see http://code.google.com/p/googleappengine/issues/detail?id=2196 */
@Test
public void testFilteringByAncestor() throws Exception
{
Objectify ofy = this.fact.begin();
Trivial triv = new Trivial(null, 3);
Key<Trivial> trivKey = ofy.put(triv);
Child child = new Child(trivKey, "blah");
ofy.put(child);
Iterator<Child> it = ofy.<Child>query().ancestor(trivKey).iterator();
assert it.hasNext(); // fails due to known GAE SDK bug
Child fetched = it.next();
assert !it.hasNext();
assert child.getId().equals(fetched.getId());
}
/** */
@Test
public void testIN() throws Exception
{
Objectify ofy = this.fact.begin();
Trivial triv1 = new Trivial("foo", 3);
Trivial triv2 = new Trivial("bar", 3);
ofy.put(triv1);
ofy.put(triv2);
List<String> conditions = Arrays.asList(new String[] {"foo", "bar", "baz"});
List<Trivial> result = ofy.query(Trivial.class).filter("someString in", conditions).list();
assert result.size() == 2;
long id1 = result.get(0).getId();
long id2 = result.get(1).getId();
assert id1 == triv1.getId() || id1 == triv2.getId();
assert id2 == triv1.getId() || id2 == triv2.getId();
}
/** */
@Test
public void testINfilteringOnStringName() throws Exception
{
Objectify ofy = this.fact.begin();
NamedTrivial triv1 = new NamedTrivial("foo", null, 3);
NamedTrivial triv2 = new NamedTrivial("bar", null, 3);
ofy.put(triv1);
ofy.put(triv2);
List<String> conditions = Arrays.asList(new String[] {"foo", "bar", "baz"});
List<NamedTrivial> result = ofy.query(NamedTrivial.class).filter("name in", conditions).list();
assert result.size() == 2;
String id1 = result.get(0).getName();
String id2 = result.get(1).getName();
assert id1.equals("foo") || id1.equals("bar");
assert id2.equals("foo") || id2.equals("bar");
}
/** */
@Test
public void testINfilteringWithKeySpecial() throws Exception
{
Objectify ofy = this.fact.begin();
Trivial triv1 = new Trivial("foo", 3);
Key<Trivial> key1 = ofy.put(triv1);
Set<Key<Trivial>> singleton = Collections.singleton(key1);
List<Trivial> result = ofy.query(Trivial.class).filter("__key__ in", singleton).list();
assert result.size() == 1;
assert triv1.getId().equals(result.get(0).getId());
}
/** */
@Test
public void testINfilteringWithKeyField() throws Exception
{
Objectify ofy = this.fact.begin();
Key<Employee> bobKey = new Key<Employee>(Employee.class, "bob");
Employee fred = new Employee("fred", bobKey);
ofy.put(fred);
Set<Key<Employee>> singleton = Collections.singleton(bobKey);
List<Employee> result = ofy.query(Employee.class).filter("manager in", singleton).list();
assert result.size() == 1;
assert result.get(0).getName().equals("fred");
}
}