package org.atomhopper.hibernate;
import static org.mockito.Mockito.mock;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import org.atomhopper.adapter.jpa.PersistedCategory;
import org.atomhopper.adapter.jpa.PersistedEntry;
import org.atomhopper.adapter.jpa.PersistedFeed;
import org.atomhopper.dbal.AtomDatabaseException;
import org.atomhopper.hibernate.actions.ComplexSessionAction;
import org.atomhopper.hibernate.actions.SimpleSessionAction;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
/**
* User: sbrayman
* Date: 2/27/12
*/
@RunWith(Enclosed.class)
public class HibernateFeedRepositoryTest {
public static class WhenPerformingSimpleAction {
HibernateFeedRepository feedRepository;
Map<String, String> parameters;
SimpleSessionAction simpleSessionAction;
@Before
public void setup() throws Exception {
parameters = new HashMap<String, String>();
//parameters.put("hibernate.connection.url", "jdbc:h2:/opt/atomhopper/atom-hopper-db"); //removed to trigger exception
parameters.put("hibernate.connection.driver_class", "org.h2.Driver");
parameters.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
parameters.put("hibernate.connection.username", "sa");
parameters.put("hibernate.connection.password", "");
parameters.put("hibernate.hbm2ddl.auto", "update");
feedRepository = new HibernateFeedRepository(parameters);
simpleSessionAction = mock(SimpleSessionAction.class);
}
@Test(expected=AtomDatabaseException.class)
public void shouldThrowAtomDatabaseException() throws Exception {
feedRepository.performSimpleAction(simpleSessionAction);
}
}
public static class WhenPerformingComplexAction {
HibernateFeedRepository feedRepository;
Map<String, String> parameters;
ComplexSessionAction complexSessionAction;
@Before
public void setup() throws Exception {
parameters = new HashMap<String, String>();
parameters.put("hibernate.connection.driver_class", "org.h2.Driver");
parameters.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
parameters.put("hibernate.connection.username", "sa");
parameters.put("hibernate.connection.password", "");
parameters.put("hibernate.hbm2ddl.auto", "update");
feedRepository = new HibernateFeedRepository(parameters);
complexSessionAction = mock(ComplexSessionAction.class);
}
/*This should throw the error because */
@Test(expected=AtomDatabaseException.class)
public void shouldThrowAtomDatabaseException() throws Exception {
feedRepository.performComplexAction(complexSessionAction);
}
}
public static class WhenCreatingEntry {
static HibernateFeedRepository feedRepository;
@BeforeClass
public static void setup() throws Exception {
Map<String, String> parameters;
parameters = new HashMap<String, String>();
parameters.put("hibernate.connection.driver_class", "org.h2.Driver");
parameters.put("hibernate.connection.url", "jdbc:h2:mem:WhenCreatingFeed");
parameters.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
parameters.put("hibernate.connection.username", "sa");
parameters.put("hibernate.connection.password", "");
parameters.put("hibernate.hbm2ddl.auto", "update");
feedRepository = new HibernateFeedRepository(parameters);
PersistedEntry entry = new PersistedEntry("entryId");
entry.setCategories(Collections.singleton(new PersistedCategory("term")));
PersistedFeed feed = new PersistedFeed("feedName", "feedId");
entry.setFeed(feed);
feedRepository.saveEntry(entry);
}
@Test
public void shouldAlsoCreateFeed() throws Exception {
final Collection<PersistedFeed> feeds = feedRepository.getAllFeeds();
assertEquals(1, feeds.size());
final PersistedFeed feed = feeds.iterator().next();
assertEquals("feedName", feed.getName());
assertEquals("feedId", feed.getFeedId());
}
@Test
public void shouldFindEntry() throws Exception {
final PersistedEntry entry = feedRepository.getEntry("entryId", "feedName");
assertEquals("entryId", entry.getEntryId());
}
@Test
public void shouldCreateCategories() {
feedRepository.performSimpleAction(new SimpleSessionAction() {
@Override
public void perform(Session liveSession) {
final PersistedEntry entry = (PersistedEntry) liveSession.createCriteria(PersistedEntry.class)
.add(Restrictions.idEq("entryId")).add(Restrictions.eq("feed.name", "feedName")).uniqueResult();
assertEquals(1, entry.getCategories().size());
final PersistedCategory category = entry.getCategories().iterator().next();
assertEquals("term", category.getTerm());
}
});
}
@Test
public void shouldFindEntryInFeed() throws Exception {
feedRepository.performSimpleAction(new SimpleSessionAction() {
@Override
public void perform(Session liveSession) {
final List feeds = liveSession.createCriteria(PersistedFeed.class).list();
final PersistedFeed feed = (PersistedFeed) feeds.iterator().next();
assertEquals(1, feed.getEntries().size());
final PersistedEntry entry = feed.getEntries().iterator().next();
assertEquals("entryId", entry.getEntryId());
}
});
}
}
public static class WhenGettingCategories {
static HibernateFeedRepository feedRepository;
static Set<PersistedCategory> categories;
@BeforeClass
public static void setup() throws Exception {
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("hibernate.connection.driver_class", "org.h2.Driver");
parameters.put("hibernate.connection.url", "jdbc:h2:mem:WhenGettingCategories");
parameters.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
parameters.put("hibernate.connection.username", "sa");
parameters.put("hibernate.connection.password", "");
parameters.put("hibernate.hbm2ddl.auto", "update");
feedRepository = new HibernateFeedRepository(parameters);
PersistedEntry entry1 = new PersistedEntry("entryId1");
PersistedCategory cat1 = new PersistedCategory("cat1");
PersistedCategory cat2 = new PersistedCategory("cat2");
entry1.setCategories(new HashSet<PersistedCategory>(Arrays.asList(cat1, cat2)));
PersistedEntry entry2 = new PersistedEntry("entryId2");
PersistedCategory cat3 = new PersistedCategory("cat3");
entry2.setCategories(Collections.singleton(cat3));
PersistedFeed feed = new PersistedFeed("feedName", "feedId");
for (PersistedEntry entry : new PersistedEntry[] { entry1, entry2 }) {
entry.setFeed(feed);
feedRepository.saveEntry(entry);
}
categories = feedRepository.getCategoriesForFeed("feedName");
for (PersistedCategory category : categories) {
System.out.println(category.getTerm());
}
}
@Test
public void shouldContainExpectedCategories() throws Exception {
assertTrue(categories.containsAll(Arrays.asList(
new PersistedCategory("cat1"), new PersistedCategory("cat2"), new PersistedCategory("cat3")
)));
}
@Test
public void shouldNotContainOtherCategories() throws Exception {
assertEquals(3, categories.size());
}
}
public static class WhenOperatingInParallel {
static HibernateFeedRepository feedRepository;
final CyclicBarrier barrier = new CyclicBarrier(2);
static Runner runner1 = new Runner();
static Runner runner2 = new Runner();
@BeforeClass
public static void setup() throws Exception {
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("hibernate.connection.driver_class", "org.h2.Driver");
parameters.put("hibernate.connection.url", "jdbc:h2:mem:WhenOperatingInParallel");
parameters.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
parameters.put("hibernate.connection.username", "sa");
parameters.put("hibernate.connection.password", "");
parameters.put("hibernate.hbm2ddl.auto", "update");
feedRepository = new HibernateFeedRepository(parameters);
}
static class Runner {
Thread t;
interface Operation<T> {
T run();
}
interface Future<T> {
T get(long timeout) throws InterruptedException;
}
<T> Future<T> run(final Operation<T> op) {
final ArrayList<T> result = new ArrayList<T>(1);
final ArrayList<RuntimeException> exception = new ArrayList<RuntimeException>(1);
t = new Thread(new Runnable() {
@Override
public void run() {
try {
result.add(op.run());
} catch (RuntimeException e) {
exception.add(e);
}
}
});
t.start();
return new Future<T>() {
@Override
public T get(long timeout) throws InterruptedException {
t.join(timeout);
if (t.isAlive()) {
t.interrupt();
t.join();
}
if (!exception.isEmpty()) {
throw new RuntimeException("Operation threw exception", exception.get(0));
}
return result.get(0);
}
};
}
}
@Test
public void shouldCreateCategoriesWithoutDuplicates() throws Exception {
final Runner.Future<Integer> r1 = runner1.run(new Runner.Operation<Integer>() {
@Override
public Integer run() {
final PersistedEntry entry = new PersistedEntry("entry1");
entry.setCategories(Collections.singleton(new PersistedCategory("cat")));
PersistedFeed feed = new PersistedFeed("feed1", "feed1");
feed.setEntries(Collections.singleton(entry));
entry.setFeed(feed);
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
feedRepository.saveEntry(entry);
return null;
}
});
final Runner.Future<Integer> r2 = runner2.run(new Runner.Operation<Integer>() {
@Override
public Integer run() {
final PersistedEntry entry = new PersistedEntry("entry2");
entry.setCategories(Collections.singleton(new PersistedCategory("cat")));
PersistedFeed feed = new PersistedFeed("feed2", "feed2");
feed.setEntries(Collections.singleton(entry));
entry.setFeed(feed);
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
feedRepository.saveEntry(entry);
return null;
}
});
r1.get(3000);
r2.get(3000);
}
@Test
public void shouldUpdateCategoriesWithoutDuplicates() throws Exception {
final Runner.Future<Integer> r1 = runner1.run(new Runner.Operation<Integer>() {
@Override
public Integer run() {
final Set<PersistedCategory> categories = Collections.singleton(new PersistedCategory("update"));
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
feedRepository.updateCategories(categories);
return null;
}
});
final Runner.Future<Integer> r2 = runner2.run(new Runner.Operation<Integer>() {
@Override
public Integer run() {
final Set<PersistedCategory> categories = Collections.singleton(new PersistedCategory("update"));
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
feedRepository.updateCategories(categories);
return null;
}
});
r1.get(3000);
r2.get(3000);
}
}
}