Add template for assignment 1
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
package dst.ass1.kv;
|
||||
|
||||
public interface ISessionManager {
|
||||
|
||||
/**
|
||||
* Creates a new session id and stores the userId and session timeout under the given id in the session store.
|
||||
*
|
||||
* @param userId the user to create the session for
|
||||
* @param timeToLive the session timeout after which the session expires in seconds
|
||||
* @return the session id.
|
||||
* @throws SessionCreationFailedException if the session couldn't be created, e.g., due to a failed transaction
|
||||
*/
|
||||
String createSession(Long userId, int timeToLive) throws SessionCreationFailedException;
|
||||
|
||||
/**
|
||||
* Sets a key--value pair in the given session.
|
||||
*
|
||||
* @param sessionId the session to store the variable in
|
||||
* @param key the name of the variable
|
||||
* @param value the value
|
||||
* @throws SessionNotFoundException if the session wasn't found
|
||||
*/
|
||||
void setSessionVariable(String sessionId, String key, String value) throws SessionNotFoundException;
|
||||
|
||||
/**
|
||||
* Returns the value of the given session variable.
|
||||
*
|
||||
* @param sessionId the session id
|
||||
* @param key the name of the variable
|
||||
* @return the variable value, or null if it doesn't exist
|
||||
* @throws SessionNotFoundException if the given session id has expired or doesn't exist
|
||||
*/
|
||||
String getSessionVariable(String sessionId, String key) throws SessionNotFoundException;
|
||||
|
||||
/**
|
||||
* Returns the user to whom the given session belongs.
|
||||
*
|
||||
* @param sessionId the session id
|
||||
* @return the user id
|
||||
* @throws SessionNotFoundException if the given session id has expired or doesn't exist
|
||||
*/
|
||||
Long getUserId(String sessionId) throws SessionNotFoundException;
|
||||
|
||||
/**
|
||||
* Returns the current time-to-live for the given session.
|
||||
*
|
||||
* @param sessionId the session id
|
||||
* @return the session ttl in seconds
|
||||
* @throws SessionNotFoundException if the given session id has expired or doesn't exist
|
||||
*/
|
||||
int getTimeToLive(String sessionId) throws SessionNotFoundException;
|
||||
|
||||
/**
|
||||
* Checks whether the given user has an open session, if so, the session id is returned (and the timeout
|
||||
* parameter ignored), otherwise a new session is created with the given timeout and the newly generated id is
|
||||
* returned.
|
||||
*
|
||||
* @param userId the user to require the session for
|
||||
* @param timeToLive the session timeout after which the session expires in seconds
|
||||
* @return the session id.
|
||||
* @throws SessionCreationFailedException if the session couldn't be created, e.g., due to a failed transaction
|
||||
*/
|
||||
String requireSession(Long userId, int timeToLive) throws SessionCreationFailedException;
|
||||
|
||||
/**
|
||||
* Closes whatever underlying connection is required to maintain the session manager.
|
||||
*/
|
||||
void close();
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package dst.ass1.kv;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
public interface ISessionManagerFactory {
|
||||
/**
|
||||
* Creates an implementation of an {@link ISessionManager}.
|
||||
*
|
||||
* @param properties the properties to use for instantiation
|
||||
* @return a session manager object
|
||||
*/
|
||||
ISessionManager createSessionManager(Properties properties);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package dst.ass1.kv;
|
||||
|
||||
/**
|
||||
* Exception indicating that a request to create a new session could not be fulfilled.
|
||||
*/
|
||||
public class SessionCreationFailedException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public SessionCreationFailedException() {
|
||||
}
|
||||
|
||||
public SessionCreationFailedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public SessionCreationFailedException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public SessionCreationFailedException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package dst.ass1.kv;
|
||||
|
||||
/**
|
||||
* Exception to indicate that <i>this is not the session you are looking for</i>.
|
||||
*/
|
||||
public class SessionNotFoundException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public SessionNotFoundException() {
|
||||
}
|
||||
|
||||
public SessionNotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public SessionNotFoundException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public SessionNotFoundException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package dst.ass1.kv.impl;
|
||||
|
||||
import dst.ass1.kv.ISessionManager;
|
||||
import dst.ass1.kv.ISessionManagerFactory;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
public class SessionManagerFactory implements ISessionManagerFactory {
|
||||
|
||||
@Override
|
||||
public ISessionManager createSessionManager(Properties properties) {
|
||||
// TODO
|
||||
// read "redis.host" and "redis.port" from the properties
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package dst.ass1.kv;
|
||||
|
||||
import org.junit.rules.ExternalResource;
|
||||
import redis.clients.jedis.Jedis;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Drops the entire key space of a redis instance before and after a test run.
|
||||
*/
|
||||
public class RedisCleaner extends ExternalResource {
|
||||
|
||||
private Properties properties;
|
||||
private Jedis jedis;
|
||||
|
||||
@Override
|
||||
protected void before() throws IOException {
|
||||
properties = loadProperties();
|
||||
|
||||
String host = properties.getProperty("redis.host");
|
||||
int port = Integer.parseInt(properties.getProperty("redis.port"));
|
||||
jedis = new Jedis(host, port);
|
||||
|
||||
// completely clear the redis instance before each test
|
||||
jedis.flushAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void after() {
|
||||
// completely clear the redis instance after each test
|
||||
try {
|
||||
jedis.flushAll();
|
||||
} finally {
|
||||
// close the connection pool
|
||||
jedis.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return loaded redis properties
|
||||
*/
|
||||
public Properties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public Jedis getJedis() {
|
||||
return jedis;
|
||||
}
|
||||
|
||||
private Properties loadProperties() throws IOException {
|
||||
Properties properties = new Properties();
|
||||
try (InputStream in = getClass().getClassLoader().getResourceAsStream("redis.properties")) {
|
||||
properties.load(in);
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package dst.ass1.kv.tests;
|
||||
|
||||
import dst.ass1.kv.ISessionManager;
|
||||
import dst.ass1.kv.ISessionManagerFactory;
|
||||
import dst.ass1.kv.RedisCleaner;
|
||||
import dst.ass1.kv.SessionNotFoundException;
|
||||
import dst.ass1.kv.impl.SessionManagerFactory;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class Ass1_5_1Test {
|
||||
|
||||
@Rule
|
||||
public RedisCleaner redisRule = new RedisCleaner();
|
||||
|
||||
private ISessionManager sessionManager;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
ISessionManagerFactory sessionManagerFactory = new SessionManagerFactory();
|
||||
|
||||
sessionManager = sessionManagerFactory.createSessionManager(redisRule.getProperties());
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
sessionManager.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createSession_createsSessionId() throws Exception {
|
||||
String sessionId = sessionManager.createSession(1337L, 15000);
|
||||
assertNotNull(sessionId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAndSetSessionVariable_behavesCorrectly() throws Exception {
|
||||
String sessionId = sessionManager.createSession(1337L, 15000);
|
||||
sessionManager.setSessionVariable(sessionId, "f00", "bar");
|
||||
assertEquals("bar", sessionManager.getSessionVariable(sessionId, "f00"));
|
||||
}
|
||||
|
||||
@Test(expected = SessionNotFoundException.class)
|
||||
public void setSessionVariable_forNonExistingSession_throwsSessionNotFoundException() throws Exception {
|
||||
sessionManager.setSessionVariable("nonExistingSessionId", "f00", "bar");
|
||||
}
|
||||
|
||||
@Test(expected = SessionNotFoundException.class)
|
||||
public void getSessionVariable_forNonExistingSession_throwsSessionNotFoundException() throws Exception {
|
||||
sessionManager.getSessionVariable("nonExistingSessionId", "f00");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSessionVariable_onNonExistingVariable_returnsNull() throws Exception {
|
||||
String sessionId = sessionManager.createSession(1337L, 15000);
|
||||
String value = sessionManager.getSessionVariable(sessionId, "f00");
|
||||
assertNull(value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUserId_returnsCorrectUserID() throws Exception {
|
||||
Long userId = 1337L;
|
||||
String sessionId = sessionManager.createSession(userId, 15000);
|
||||
assertEquals(userId, sessionManager.getUserId(sessionId));
|
||||
}
|
||||
|
||||
@Test(expected = SessionNotFoundException.class)
|
||||
public void getUserId_forNonExistingSession_throwsException() throws Exception {
|
||||
sessionManager.getUserId("nonExistingSessionId");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTimeToLive_returnsCorrectValue() throws Exception {
|
||||
String sessionId = sessionManager.createSession(1337L, 60);
|
||||
int ttl = sessionManager.getTimeToLive(sessionId);
|
||||
assertThat(ttl, allOf(greaterThan(57), lessThan(61)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTimeToLive_afterExpiry_throwsSessionNotFoundException() throws Exception {
|
||||
String sessionId = sessionManager.createSession(1337L, 2);
|
||||
int ttl = sessionManager.getTimeToLive(sessionId);
|
||||
assertThat(ttl, greaterThan(0));
|
||||
Thread.sleep(3000);
|
||||
|
||||
assertThrows(SessionNotFoundException.class, () -> {
|
||||
sessionManager.getTimeToLive(sessionId);
|
||||
});
|
||||
}
|
||||
|
||||
@Test(expected = SessionNotFoundException.class)
|
||||
public void getTimeToLive_forNonExistingSession_throwsSessionNotFoundException() throws Exception {
|
||||
sessionManager.getTimeToLive("nonExistingSessionId");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package dst.ass1.kv.tests;
|
||||
|
||||
import dst.ass1.kv.ISessionManager;
|
||||
import dst.ass1.kv.ISessionManagerFactory;
|
||||
import dst.ass1.kv.RedisCleaner;
|
||||
import dst.ass1.kv.impl.SessionManagerFactory;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
public class Ass1_5_2Test {
|
||||
|
||||
@Rule
|
||||
public RedisCleaner redisRule = new RedisCleaner();
|
||||
|
||||
private ISessionManager sessionManager;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
ISessionManagerFactory sessionManagerFactory = new SessionManagerFactory();
|
||||
|
||||
sessionManager = sessionManagerFactory.createSessionManager(redisRule.getProperties());
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
sessionManager.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequireSessionForExistingSession_existingIdReturned() throws Exception {
|
||||
String newId = sessionManager.createSession(1337L, 30000);
|
||||
assertNotNull(newId);
|
||||
|
||||
String requiredId = sessionManager.requireSession(1337L, 15000);
|
||||
assertEquals(newId, requiredId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequireSessionForNonExistingSession_newSessionCreated() throws Exception {
|
||||
String sessionId = sessionManager.requireSession(1337L, 15000);
|
||||
|
||||
assertEquals(Long.valueOf(1337L), sessionManager.getUserId(sessionId));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package dst.ass1.kv.tests;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
import org.junit.runners.Suite.SuiteClasses;
|
||||
|
||||
@RunWith(Suite.class)
|
||||
@SuiteClasses( {
|
||||
Ass1_5_1Test.class,
|
||||
Ass1_5_2Test.class
|
||||
})
|
||||
public class Ass1_5_Suite {
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<configuration>
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} - %highlight(%5p) [%12.12thread] %cyan(%-40.40logger{39}): %m%n</pattern>
|
||||
</encoder>
|
||||
|
||||
</appender>
|
||||
|
||||
<root level="${log.level:-INFO}">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</root>
|
||||
</configuration>
|
||||
@@ -0,0 +1,4 @@
|
||||
# you can change this to, e.g., 127.0.0.1 if you have a local redis instance
|
||||
redis.host=192.168.99.99
|
||||
#redis.host=127.0.0.1
|
||||
redis.port=6379
|
||||
Reference in New Issue
Block a user