package com.wesabe.grendel.resources.tests; import static org.fest.assertions.Assertions.*; import static org.mockito.Mockito.*; import java.security.SecureRandom; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import org.junit.Before; import org.junit.Test; import org.junit.experimental.runners.Enclosed; import org.junit.runner.RunWith; import org.mockito.InOrder; import com.google.inject.Provider; import com.wesabe.grendel.auth.Credentials; import com.wesabe.grendel.auth.Session; import com.wesabe.grendel.entities.Document; import com.wesabe.grendel.entities.User; import com.wesabe.grendel.entities.dao.DocumentDAO; import com.wesabe.grendel.entities.dao.UserDAO; import com.wesabe.grendel.openpgp.UnlockedKeySet; import com.wesabe.grendel.resources.LinkResource; @RunWith(Enclosed.class) public class LinkResourceTest { private static abstract class Context { protected UserDAO userDAO; protected DocumentDAO documentDAO; protected SecureRandom random; protected Credentials credentials; protected Session session; protected User user, reader; protected UnlockedKeySet keySet; protected Document document; protected byte[] body; protected LinkResource resource; public void setup() throws Exception { this.body = "one two three four five".getBytes(); this.user = mock(User.class); this.reader = mock(User.class); this.keySet = mock(UnlockedKeySet.class); this.document = mock(Document.class); when(document.decryptBody(keySet)).thenReturn(body); this.session = mock(Session.class); when(session.getUser()).thenReturn(user); when(session.getKeySet()).thenReturn(keySet); this.userDAO = mock(UserDAO.class); when(userDAO.findById("frank")).thenReturn(reader); this.documentDAO = mock(DocumentDAO.class); when(documentDAO.findByOwnerAndName(user, "document1.txt")).thenReturn(document); this.random = mock(SecureRandom.class); this.credentials = mock(Credentials.class); when(credentials.buildSession(userDAO, "bob")).thenReturn(session); this.resource = new LinkResource(userDAO, documentDAO, new Provider<SecureRandom>() { @Override public SecureRandom get() { return random; } }); } } public static class Creating_A_Link extends Context { @Before @Override public void setup() throws Exception { super.setup(); } @Test public void itThrowsA404IfTheReaderDoesNotExist() throws Exception { when(userDAO.findById("frank")).thenReturn(null); try { resource.createLink(credentials, "bob", "document1.txt", "frank"); } catch (WebApplicationException e) { assertThat(e.getResponse().getStatus()).isEqualTo(Status.NOT_FOUND.getStatusCode()); } } @Test public void itThrowsA404IfTheDocumentDoesNotExist() throws Exception { when(documentDAO.findByOwnerAndName(user, "document1.txt")).thenReturn(null); try { resource.createLink(credentials, "bob", "document1.txt", "frank"); } catch (WebApplicationException e) { assertThat(e.getResponse().getStatus()).isEqualTo(Status.NOT_FOUND.getStatusCode()); } } @Test public void itLinksTheUserReEncryptsTheDocumentAndSavesIt() throws Exception { resource.createLink(credentials, "bob", "document1.txt", "frank"); final InOrder inOrder = inOrder(document, documentDAO); inOrder.verify(document).linkUser(reader); inOrder.verify(document).encryptAndSetBody(keySet, random, body); inOrder.verify(documentDAO).saveOrUpdate(document); } @Test public void itReturnsA204NoContent() throws Exception { final Response r = resource.createLink(credentials, "bob", "document1.txt", "frank"); assertThat(r.getStatus()).isEqualTo(Status.NO_CONTENT.getStatusCode()); } } public static class Deleting_A_Link extends Context { @Before @Override public void setup() throws Exception { super.setup(); } @Test public void itThrowsA404IfTheReaderDoesNotExist() throws Exception { when(userDAO.findById("frank")).thenReturn(null); try { resource.deleteLink(credentials, "bob", "document1.txt", "frank"); } catch (WebApplicationException e) { assertThat(e.getResponse().getStatus()).isEqualTo(Status.NOT_FOUND.getStatusCode()); } } @Test public void itThrowsA404IfTheDocumentDoesNotExist() throws Exception { when(documentDAO.findByOwnerAndName(user, "document1.txt")).thenReturn(null); try { resource.deleteLink(credentials, "bob", "document1.txt", "frank"); } catch (WebApplicationException e) { assertThat(e.getResponse().getStatus()).isEqualTo(Status.NOT_FOUND.getStatusCode()); } } @Test public void itUnlinksTheUserReEncryptsTheDocumentAndSavesIt() throws Exception { resource.deleteLink(credentials, "bob", "document1.txt", "frank"); final InOrder inOrder = inOrder(document, documentDAO); inOrder.verify(document).unlinkUser(reader); inOrder.verify(document).encryptAndSetBody(keySet, random, body); inOrder.verify(documentDAO).saveOrUpdate(document); } @Test public void itReturnsA204NoContent() throws Exception { final Response r = resource.deleteLink(credentials, "bob", "document1.txt", "frank"); assertThat(r.getStatus()).isEqualTo(Status.NO_CONTENT.getStatusCode()); } } }