/*
* $Id$
*
* Copyright 2008 Glencoe Software, Inc. All rights reserved.
* Use is subject to license terms supplied in LICENSE.txt
*/
package ome.server.utests;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import ome.api.IQuery;
import ome.model.containers.Dataset;
import ome.model.containers.Project;
import ome.model.core.Image;
import ome.model.meta.EventLog;
import ome.services.eventlogs.AllEntitiesPseudoLogLoader;
import ome.services.eventlogs.AllEventsLogLoader;
import ome.services.eventlogs.EventBacklog;
import ome.services.eventlogs.EventLogLoader;
import ome.services.fulltext.FullTextIndexer;
import org.jmock.Mock;
import org.jmock.MockObjectTestCase;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/**
* Tests how the {@link EventLogLoader} and the {@link EventBacklog} work
* together. The tests below may look somewhat strange. This is due to the fact
* that the {@link FullTextIndexer} first consumes all the {@link EventLog}'s
* from the {@link EventLogLoader} before processing them.
*/
@Test(groups = { "query", "fulltext" })
public class EventLogLoadersTest extends MockObjectTestCase {
EventLogLoader ell;
EventLog el;
List<EventLog> list;
Mock q;
IQuery svc;
@BeforeMethod
public void setup() {
q = mock(IQuery.class);
svc = (IQuery) q.proxy();
}
public void testBasic() throws Exception {
el = new EventLog(1L, false);
ell = new ListLogLoader();
((ListLogLoader) ell).logs.add(0, el);
((ListLogLoader) ell).logs.add(1, null);
assertTrue(ell.hasNext());
assertEquals(el, ell.next());
assertFalse(ell.hasNext());
try {
ell.next();
fail("Should throw");
} catch (Exception nsee) {
// ok
}
assertTrue(ell.more() == 0); // always true
}
public void testAllEntitiesLoader() throws Exception {
ell = new AllEntitiesPseudoLogLoader();
ell.setQueryService(svc);
((AllEntitiesPseudoLogLoader) ell).setClasses(Collections
.singleton("cls1"));
assertTrue(ell.more() > 0);
returnNotNull();
assertTrue(ell.hasNext());
// Returns a pseudo EventLog so we don't need to test of identity
returnNull();
assertNotNull(ell.next().getEntityId());
assertFalse(ell.hasNext());
assertFalse(ell.more() > 0);
}
@Test(groups = "broken")
// Error getting ordering of mocks setup
public void testAllEventsLoader() throws Exception {
ell = new AllEventsLogLoader();
ell.setQueryService(svc);
// First query invocation is to get the maximum value
EventLog first = new EventLog(1L, false);
EventLog last = new EventLog(2L, false);
q.expects(once()).method("findByQuery").with(
eq("select el from EventLog el order by id desc"), ANYTHING)
.will(returnValue(last)).id("last");
returnEl(last);
q.expects(once()).method("findByQuery").after("last").will(
returnValue(first)).id("first");
assertTrue(ell.hasNext());
assertTrue(ell.more() > 0); // More as long as last was positive
q.expects(once()).method("findByQuery").after("first").will(
returnValue(last)).id("lastagain");
assertEquals(last, ell.next());
q.expects(once()).method("findByQuery").after("lastagain").will(
returnValue(null)).id("null");
assertEquals(el, ell.next());
assertFalse(ell.hasNext());
assertFalse(ell.more() > 0);
}
@Test
public void testHasNextReloadsAfterADiscontinuation() {
ListLogLoader lll = new ListLogLoader();
lll.logs.add(new EventLog(1L, false));
boolean reached = false;
for (EventLog test : lll) {
reached = true;
assertNotNull(test);
}
assertTrue(reached);
assertTrue(lll.logs.size() == 0);
reached = false;
lll.logs.add(new EventLog(2L, false));
for (EventLog test : lll) {
reached = true;
assertNotNull(test);
}
assertTrue(reached);
assertTrue(lll.logs.size() == 0);
}
@Test
public void testBatchSize() {
el = new EventLog(1L, false);
ell = new EventLogLoader() {
@Override
protected EventLog query() {
return el;
}
@Override
public long more() {
return 0;
}
};
int count = 0;
for (EventLog test : ell) {
count++;
assertEquals(test, el);
}
assertEquals(EventLogLoader.DEFAULT_BATCH_SIZE, count);
count = 0;
for (EventLog test : ell) {
count++;
assertEquals(test, el);
}
assertEquals(EventLogLoader.DEFAULT_BATCH_SIZE, count);
}
@Test(groups = "ticket:1102")
public void testBacklog() {
el = null;
ell = new EventLogLoader() {
@Override
protected EventLog query() {
return el;
}
@Override
public long more() {
return 0;
}
};
// BATCH:1
// LOADING
assertFalse(ell.hasNext());
// FLUSHING
assertTrue(ell.addEventLog(Image.class, 1L));
assertTrue(ell.addEventLog(Image.class, 2L));
// Adding twice should not work
assertFalse(ell.addEventLog(Image.class, 2L));
// BATCH:2
// Load the two from backlog
assertNotNull(ell.next());
assertNotNull(ell.next());
assertFalse(ell.hasNext());
// Now the backlog is empty
// During flushing of the backlog,
// nothing should be addable.
assertFalse(ell.addEventLog(Image.class, 2L));
// Now we should be finished
assertFalse(ell.hasNext());
}
//
// Testing the structure:
//
// . p1 --> d2 --> i4
// . \___> d3 --> i5
//
@Test(groups = "ticket:1102")
public void testBacklogAdvanced() {
list = new ArrayList<EventLog>();
list.add(new EventLog(1L, Project.class.getName(), "INSERT", null));
list.add(new EventLog(2L, Dataset.class.getName(), "INSERT", null));
list.add(new EventLog(3L, Dataset.class.getName(), "INSERT", null));
list.add(new EventLog(4L, Image.class.getName(), "INSERT", null));
list.add(new EventLog(5L, Image.class.getName(), "INSERT", null));
ell = new EventLogLoader() {
@Override
protected EventLog query() {
return list.size() == 0 ? null : list.remove(0);
}
@Override
public long more() {
return 0;
}
};
EventLog current;
//
// LOAD : up to batch size things get loaded
//
assertTrue(ell.hasNext());
current = ell.next();
assertEquals(new Long(1L), current.getEntityId());
current = ell.next();
assertEquals(new Long(2L), current.getEntityId());
current = ell.next();
assertEquals(new Long(3L), current.getEntityId());
current = ell.next();
assertEquals(new Long(4L), current.getEntityId());
current = ell.next();
assertEquals(new Long(5L), current.getEntityId());
// end loop
assertFalse(ell.hasNext());
//
// FLUSH : lots of things get added (only once)
//
assertTrue(ell.addEventLog(Project.class, 1L));
assertTrue(ell.addEventLog(Dataset.class, 2L));
assertTrue(ell.addEventLog(Dataset.class, 3L));
assertTrue(ell.addEventLog(Image.class, 4L));
assertTrue(ell.addEventLog(Image.class, 5L));
assertFalse(ell.addEventLog(Project.class, 1L));
assertFalse(ell.addEventLog(Dataset.class, 2L));
assertFalse(ell.addEventLog(Dataset.class, 3L));
assertFalse(ell.addEventLog(Image.class, 4L));
assertFalse(ell.addEventLog(Image.class, 5L));
//
// BACKLOG
//
assertTrue(ell.hasNext());
current = ell.next();
assertEquals(new Long(1L), current.getEntityId());
current = ell.next();
assertEquals(new Long(2L), current.getEntityId());
current = ell.next();
assertEquals(new Long(3L), current.getEntityId());
current = ell.next();
assertEquals(new Long(4L), current.getEntityId());
current = ell.next();
assertEquals(new Long(5L), current.getEntityId());
// end loop
assertFalse(ell.hasNext());
//
// FLUSH BACKLOG : nothing can be added
//
assertFalse(ell.addEventLog(Project.class, 1L));
assertFalse(ell.addEventLog(Dataset.class, 2L));
assertFalse(ell.addEventLog(Dataset.class, 3L));
assertFalse(ell.addEventLog(Image.class, 4L));
assertFalse(ell.addEventLog(Image.class, 5L));
assertFalse(ell.hasNext());
assertFalse(ell.hasNext());
assertFalse(ell.hasNext());
}
// ======================================================
private void returnEl(EventLog log) {
q.expects(once()).method("findByQuery").will(returnValue(log));
}
private void returnNull() {
returnEl(null);
}
private EventLog returnNotNull() {
EventLog log = new EventLog(1L, true);
returnEl(log);
return log;
}
private static class ListLogLoader extends EventLogLoader {
public final List<EventLog> logs = new ArrayList<EventLog>();
@Override
protected EventLog query() {
return logs.size() < 1 ? null : logs.remove(0);
}
@Override
public long more() {
return 0;
}
}
}