package org.jooby.cassandra; import static org.easymock.EasyMock.eq; import static org.easymock.EasyMock.expect; import static org.junit.Assert.assertEquals; import java.util.Date; import java.util.Map; import org.jooby.Session.Builder; import org.jooby.test.MockUnit; import org.jooby.test.MockUnit.Block; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import com.datastax.driver.core.BoundStatement; import com.datastax.driver.core.PreparedStatement; import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.ResultSetFuture; import com.datastax.driver.core.Row; import com.datastax.driver.core.Session; import com.datastax.driver.core.Statement; import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; @RunWith(PowerMockRunner.class) @PrepareForTest({CassandraSessionStore.class, Futures.class, BoundStatement.class }) public class CassandraSessionStoreTest { @SuppressWarnings("unchecked") private Block createTable = unit -> { ResultSetFuture rs = unit.mock(ResultSetFuture.class); Session session = unit.get(Session.class); expect(session.executeAsync(unit.capture(Statement.class))).andReturn(rs); unit.mockStatic(Futures.class); Futures.addCallback(eq(rs), unit.capture(FutureCallback.class)); }; private Block boundStatement = unit -> { BoundStatement statement = unit.constructor(BoundStatement.class) .args(PreparedStatement.class) .build(unit.get(PreparedStatement.class)); unit.registerMock(BoundStatement.class, statement); }; @Test public void newSessionStore30m() throws Exception { new MockUnit(Session.class) .expect(createTable) .run(unit -> { new CassandraSessionStore(unit.get(Session.class), "30m"); }); } @Test public void createTableStatement() throws Exception { new MockUnit(Session.class) .expect(createTable) .run(unit -> { new CassandraSessionStore(unit.get(Session.class), "30m"); }, unit -> { String statement = unit.captured(Statement.class).iterator().next().toString(); assertEquals("\n" + " CREATE TABLE IF NOT EXISTS session(\n" + " id varchar,\n" + " createdAt timestamp,\n" + " accessedAt timestamp,\n" + " savedAt timestamp,\n" + " attributes map<varchar, varchar>,\n" + " PRIMARY KEY(id))", statement.replace('\t', ' ')); }); } @SuppressWarnings({"unchecked", "rawtypes" }) @Test public void createTableSuccess() throws Exception { new MockUnit(Session.class, ResultSet.class) .expect(createTable) .run(unit -> { new CassandraSessionStore(unit.get(Session.class), "30m"); }, unit -> { FutureCallback success = unit.captured(FutureCallback.class).iterator().next(); success.onSuccess(unit.get(ResultSet.class)); }); } @SuppressWarnings("rawtypes") @Test public void createTableFailure() throws Exception { new MockUnit(Session.class, ResultSet.class) .expect(createTable) .run(unit -> { new CassandraSessionStore(unit.get(Session.class), "30m"); }, unit -> { FutureCallback success = unit.captured(FutureCallback.class).iterator().next(); success.onFailure(new IllegalStateException("intentional err")); }); } @Test public void newSessionStore30s() throws Exception { new MockUnit(Session.class) .expect(createTable) .run(unit -> { new CassandraSessionStore(unit.get(Session.class), "30"); }); } @Test public void save() throws Exception { new MockUnit(Session.class, org.jooby.Session.class) .expect(createTable) .expect(session("sid", 1, 2, 3, ImmutableMap.of("foo", "bar"))) .expect(insertInto(1800)) .expect(boundStatement) .expect(unit -> { BoundStatement statement = unit.get(BoundStatement.class); expect(statement.bind("sid", new Date(1), new Date(2), new Date(3), ImmutableMap.of("foo", "bar"))).andReturn(statement); Session session = unit.get(Session.class); expect(session.execute(statement)).andReturn(null); }) .run(unit -> { new CassandraSessionStore(unit.get(Session.class), "30m") .save(unit.get(org.jooby.Session.class)); }); } @Test public void create() throws Exception { new MockUnit(Session.class, org.jooby.Session.class) .expect(createTable) .expect(session("sid", 5, 6, 7, ImmutableMap.of("foo", "bar"))) .expect(insertInto(0)) .expect(boundStatement) .expect(unit -> { BoundStatement statement = unit.get(BoundStatement.class); expect(statement.bind("sid", new Date(5), new Date(6), new Date(7), ImmutableMap.of("foo", "bar"))).andReturn(statement); Session session = unit.get(Session.class); expect(session.execute(statement)).andReturn(null); }) .run(unit -> { new CassandraSessionStore(unit.get(Session.class), 0) .create(unit.get(org.jooby.Session.class)); }); } @Test public void get() throws Exception { new MockUnit(Session.class, org.jooby.Session.class, org.jooby.Session.Builder.class, ResultSet.class) .expect(createTable) .expect(unit -> { PreparedStatement statement = unit.mock(PreparedStatement.class); unit.registerMock(PreparedStatement.class, statement); Session session = unit.get(Session.class); expect(session.prepare("SELECT * FROM session WHERE id=?;")).andReturn(statement); }) .expect(unit -> { Builder builder = unit.get(org.jooby.Session.Builder.class); expect(builder.sessionId()).andReturn("sid"); }) .expect(boundStatement) .expect(unit -> { BoundStatement statement = unit.get(BoundStatement.class); expect(statement.bind("sid")).andReturn(statement); Session session = unit.get(Session.class); expect(session.execute(statement)).andReturn(unit.get(ResultSet.class)); }) .expect(unit -> { Row row = unit.mock(Row.class); Date createdAt = new Date(); Date accessedAt = new Date(); Date savedAt = new Date(); expect(row.getTimestamp("createdAt")).andReturn(createdAt); expect(row.getTimestamp("accessedAt")).andReturn(accessedAt); expect(row.getTimestamp("savedAt")).andReturn(savedAt); expect(row.getMap("attributes", String.class, String.class)) .andReturn(ImmutableMap.of("foo", "bar")); Builder builder = unit.get(org.jooby.Session.Builder.class); expect(builder.createdAt(createdAt.getTime())).andReturn(builder); expect(builder.accessedAt(accessedAt.getTime())).andReturn(builder); expect(builder.savedAt(savedAt.getTime())).andReturn(builder); expect(builder.set(ImmutableMap.of("foo", "bar"))).andReturn(builder); expect(builder.build()).andReturn(unit.get(org.jooby.Session.class)); ResultSet rs = unit.get(ResultSet.class); expect(rs.one()).andReturn(row); }) .expect(session("sid", 1, 2, 3, ImmutableMap.of("foo", "bar"))) .expect(insertInto(30)) .expect(boundStatement) .expect(unit -> { BoundStatement statement = unit.get(BoundStatement.class); expect(statement.bind("sid", new Date(1), new Date(2), new Date(3), ImmutableMap.of("foo", "bar"))).andReturn(statement); Session session = unit.get(Session.class); expect(session.execute(statement)).andReturn(null); }) .run(unit -> { new CassandraSessionStore(unit.get(Session.class), "30") .get(unit.get(org.jooby.Session.Builder.class)); }); } @Test public void delete() throws Exception { new MockUnit(Session.class, org.jooby.Session.class) .expect(createTable) .expect(unit -> { PreparedStatement statement = unit.mock(PreparedStatement.class); unit.registerMock(PreparedStatement.class, statement); Session session = unit.get(Session.class); expect(session.prepare("DELETE FROM session WHERE id=?;")).andReturn(statement); }) .expect(boundStatement) .expect(unit -> { BoundStatement statement = unit.get(BoundStatement.class); expect(statement.bind("sid")).andReturn(statement); Session session = unit.get(Session.class); expect(session.execute(statement)).andReturn(null); }) .run(unit -> { new CassandraSessionStore(unit.get(Session.class), "30") .delete("sid"); }); } @Test public void getWithoutTtl() throws Exception { new MockUnit(Session.class, org.jooby.Session.class, org.jooby.Session.Builder.class, ResultSet.class) .expect(createTable) .expect(unit -> { PreparedStatement statement = unit.mock(PreparedStatement.class); unit.registerMock(PreparedStatement.class, statement); Session session = unit.get(Session.class); expect(session.prepare("SELECT * FROM session WHERE id=?;")).andReturn(statement); }) .expect(unit -> { Builder builder = unit.get(org.jooby.Session.Builder.class); expect(builder.sessionId()).andReturn("sid"); }) .expect(boundStatement) .expect(unit -> { BoundStatement statement = unit.get(BoundStatement.class); expect(statement.bind("sid")).andReturn(statement); Session session = unit.get(Session.class); expect(session.execute(statement)).andReturn(unit.get(ResultSet.class)); }) .expect(unit -> { Row row = unit.mock(Row.class); Date createdAt = new Date(); Date accessedAt = new Date(); Date savedAt = new Date(); expect(row.getTimestamp("createdAt")).andReturn(createdAt); expect(row.getTimestamp("accessedAt")).andReturn(accessedAt); expect(row.getTimestamp("savedAt")).andReturn(savedAt); expect(row.getMap("attributes", String.class, String.class)) .andReturn(ImmutableMap.of("foo", "bar")); Builder builder = unit.get(org.jooby.Session.Builder.class); expect(builder.createdAt(createdAt.getTime())).andReturn(builder); expect(builder.accessedAt(accessedAt.getTime())).andReturn(builder); expect(builder.savedAt(savedAt.getTime())).andReturn(builder); expect(builder.set(ImmutableMap.of("foo", "bar"))).andReturn(builder); expect(builder.build()).andReturn(unit.get(org.jooby.Session.class)); ResultSet rs = unit.get(ResultSet.class); expect(rs.one()).andReturn(row); }) .run(unit -> { new CassandraSessionStore(unit.get(Session.class), "0") .get(unit.get(org.jooby.Session.Builder.class)); }); } private Block insertInto(final int ttl) { return unit -> { PreparedStatement statement = unit.mock(PreparedStatement.class); unit.registerMock(PreparedStatement.class, statement); Session session = unit.get(Session.class); String suffix = ttl > 0 ? " USING TTL " + ttl : ""; expect(session.prepare( "INSERT INTO session (id,createdAt,accessedAt,savedAt,attributes) VALUES (?,?,?,?,?)" + suffix + ";")) .andReturn(statement); }; } private Block session(final String sid, final long createdAt, final long accessedAt, final long savedAt, final Map<String, String> attributes) { return unit -> { org.jooby.Session session = unit.get(org.jooby.Session.class); expect(session.id()).andReturn(sid); expect(session.createdAt()).andReturn(createdAt); expect(session.accessedAt()).andReturn(accessedAt); expect(session.savedAt()).andReturn(savedAt); expect(session.attributes()).andReturn(attributes); }; } }