/* */ package com.googlecode.objectify.test; import com.google.appengine.api.datastore.Cursor; import com.google.appengine.api.datastore.QueryResultIterator; import com.google.common.collect.Maps; import com.googlecode.objectify.Key; import com.googlecode.objectify.impl.Chunk; import com.googlecode.objectify.impl.ChunkIterator; import com.googlecode.objectify.impl.LoadEngine; import com.googlecode.objectify.impl.ResultWithCursor; import com.googlecode.objectify.test.entity.Trivial; import com.googlecode.objectify.test.util.TestBase; import com.googlecode.objectify.util.ResultNow; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.util.Map; import static com.googlecode.objectify.test.util.TestObjectifyService.fact; import static com.googlecode.objectify.test.util.TestObjectifyService.ofy; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; /** * Lowish-level tests for chunking behavior of queries. * * @author Jeff Schnitzer <jeff@infohazard.org> */ public class QueryChunkingTests extends TestBase { private static final int BATCH_SIZE = 2; QueryResultIterator<Key<Trivial>> keysIt; Map<Key<Trivial>, Trivial> values; LoadEngine loadEngine; /** */ @BeforeMethod public void setUpExtra() { fact().register(Trivial.class); values = Maps.newHashMap(); for (int i=10; i<15; i++) { Trivial triv = new Trivial((long)i, "str"+i, i); Key<Trivial> key = ofy().save().entity(triv).now(); values.put(key, triv); } keysIt = ofy().load().type(Trivial.class).chunk(BATCH_SIZE).keys().iterator(); loadEngine = mock(LoadEngine.class); for (Map.Entry<Key<Trivial>, Trivial> entry: values.entrySet()) when(loadEngine.load(entry.getKey())).thenReturn(new ResultNow<>(entry.getValue())); } /** */ @Test public void testChunkIterator() throws Exception { ChunkIterator<Trivial> chunkIt = new ChunkIterator<>(keysIt, BATCH_SIZE, loadEngine); Chunk<Trivial> chunk; ResultWithCursor<Trivial> rc; // First chunk chunk = chunkIt.next(); rc = chunk.next(); assert rc.getResult().getId() == 10; assertCursorGetsId(rc.getCursor(), 10); assert rc.getOffset() == 0; rc = chunk.next(); assert rc.getResult().getId() == 11; assertCursorGetsId(rc.getCursor(), 10); assert rc.getOffset() == 1; // Second chunk chunk = chunkIt.next(); rc = chunk.next(); assert rc.getResult().getId() == 12; assertCursorGetsId(rc.getCursor(), 12); assert rc.getOffset() == 0; rc = chunk.next(); assert rc.getResult().getId() == 13; assertCursorGetsId(rc.getCursor(), 12); assert rc.getOffset() == 1; // Third (abbreviated) chunk chunk = chunkIt.next(); rc = chunk.next(); assert rc.getResult().getId() == 14; assertCursorGetsId(rc.getCursor(), 14); assert rc.getOffset() == 0; } /** * Assert that fetching from the cursor gets a trivial with the specified id as the first item. */ private void assertCursorGetsId(Cursor cursor, long trivId) { assert ofy().load().type(Trivial.class).startAt(cursor).first().now().getId() == trivId; } }