package org.swellrt.server.box.servlet; import static org.mockito.Matchers.anyObject; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.nio.charset.Charset; import java.util.Map; import java.util.Map.Entry; import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.swellrt.server.box.servlet.AccountService.AccountServiceData; import org.waveprotocol.box.server.account.HumanAccountData; import org.waveprotocol.box.server.account.HumanAccountDataImpl; import org.waveprotocol.box.server.authentication.SessionManager; import org.waveprotocol.box.server.persistence.AccountAttachmentStore; import org.waveprotocol.box.server.persistence.AccountStore; import org.waveprotocol.box.server.persistence.PersistenceException; import org.waveprotocol.box.server.persistence.memory.MemoryStore; import org.waveprotocol.wave.model.util.CollectionUtils; import org.waveprotocol.wave.model.wave.InvalidParticipantAddress; import org.waveprotocol.wave.model.wave.ParticipantId; import com.google.common.collect.ImmutableMap; import junit.framework.TestCase; public class AccountServiceTest extends TestCase { private final static String IMAGE_BASE64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAZCAYAAAAv3j5gAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQZJREFUeNrsle0NgyAQhqHpf92gjuAIHcFuwAgdoSN0BN3AETqCI3QEN7hy5kguiHgF2vRHL3kT0YPnPgAVAKhSstZaPULfjqqQaa0XiFUVdCiYyYzLkbqVzwcgQOO2GGgDwmEmG2StiUC4DPkvg9GqTsgGhDI44cpTxUgji9fkf6NnI4bRAuMb0TlNDBzzwwQ6HilkwHr2DoN++i1xIJMI4rA7ivfQK7t498TUCzbPcm1ArvZAmhyzzS6mY98P6ku2dXtfqG9nOpioU9btHijdYMtgAr+BhkFdAJW0dCpwuOqUK2jP3+8RnoNZ2PwpuXSS9L1yws/tuj8oCzS485MwXzz3JcAARxWLH4IZZWIAAAAASUVORK5CYII="; protected static HumanAccountData createHumanAccount(ParticipantId pid, String email, String avatarFileId, String locale) { HumanAccountData account = new HumanAccountDataImpl(pid); account.setAvatarFileId(avatarFileId); account.setEmail(email); account.setLocale(locale); return account; } protected static HumanAccountData ACCOUNT_JOE = createHumanAccount( ParticipantId.ofUnsafe("joe@example.com"), "joe@mail.example.com", "image/png;image.png", "en_GB"); protected static HumanAccountData ACCOUNT_TOM = createHumanAccount( ParticipantId.ofUnsafe("tom@example.com"), "tom@mailexample.com", "image/png;image.png", "en_US"); protected static HumanAccountData ACCOUNT_MAT = createHumanAccount( ParticipantId.ofUnsafe("mat@example.com"), "mat@mail.example.com", "image/png;image.png", "es_ES"); AccountStore accountStore; AccountAttachmentStore accountAttachmentStore; AccountService service; SessionManager sessionManager; @Override protected void setUp() throws Exception { accountStore = new MemoryStore(); accountAttachmentStore = mock(AccountAttachmentStore.class); when( accountAttachmentStore.storeAvatar((ParticipantId) anyObject(), anyString(), anyString(), anyString())).thenReturn("image/png;image.png"); sessionManager = mock(SessionManager.class); service = new AccountService(sessionManager, accountStore, accountAttachmentStore, "example.com"); } protected ServletInputStream asServletInputStream(final String data) { return new ServletInputStream() { ByteArrayInputStream byteInputStream = new ByteArrayInputStream(data.getBytes(Charset.forName("UTF-8"))); int b; @Override public boolean isFinished() { return b == -1; } @Override public boolean isReady() { return true; } @Override public void setReadListener(ReadListener readListener) { } @Override public int read() throws IOException { this.b = byteInputStream.read(); return b; } }; } public void executeService(String path, String method, AccountServiceData requestData, ByteArrayOutputStream responseStream, int expectedHttpResponseCode) throws IOException { executeService(path, method, requestData, responseStream, expectedHttpResponseCode, null); } public void executeService(String path, String method, AccountServiceData requestData, ByteArrayOutputStream responseStream, int expectedHttpResponseCode, Map<String, String> parameters) throws IOException { HttpServletRequest request = mock(HttpServletRequest.class); when(request.getRequestURL()).thenReturn(new StringBuffer("http://localhost:9898")); HttpServletResponse response = mock(HttpServletResponse.class); when(request.getPathInfo()).thenReturn(path); when(request.getMethod()).thenReturn(method); if (parameters != null) { for (Entry<String, String> p : parameters.entrySet()) { when(request.getParameter(eq(p.getKey()))).thenReturn(p.getValue()); } } when(request.getInputStream()).thenReturn(asServletInputStream(requestData.toJson())); when(response.getCharacterEncoding()).thenReturn("UTF-8"); when(response.getWriter()).thenReturn(new PrintWriter(responseStream)); service.execute(request, response); verify(response).setStatus(expectedHttpResponseCode); } public void testCreateAccount() throws IOException { // Mock data when(sessionManager.getLoggedInUser((HttpSession) anyObject())).thenReturn(null); // Test AccountServiceData requestData = new AccountServiceData(); requestData.id = "joe"; requestData.email = "joe@email.example.com"; requestData.locale = "en_EN"; requestData.password = "_password_"; requestData.avatarData = IMAGE_BASE64; ByteArrayOutputStream responseStream = new ByteArrayOutputStream(); executeService("/account", "POST", requestData, responseStream, HttpServletResponse.SC_OK); AccountServiceData responseData = (AccountServiceData) ServiceData.fromJson(responseStream.toString("UTF-8"), AccountServiceData.class); assertEquals(requestData.email, responseData.email); assertEquals(requestData.locale, responseData.locale); assertTrue(responseData.avatarUrl.contains("image.png")); } public void testCreateAccountButAlreadyExists() throws IOException, InvalidParticipantAddress, PersistenceException { // Mock data accountStore.putAccount(ACCOUNT_JOE); // Test AccountServiceData requestData = new AccountServiceData(); requestData.id = "joe"; requestData.email = "joe@example.com"; requestData.locale = "en_GB"; requestData.password = "_password_"; requestData.avatarData = IMAGE_BASE64; ByteArrayOutputStream responseStream = new ByteArrayOutputStream(); executeService("/account", "POST", requestData, responseStream, HttpServletResponse.SC_FORBIDDEN); } public void testUpdateAccount() throws PersistenceException, InvalidParticipantAddress, IOException { // Mock data accountStore.putAccount(ACCOUNT_JOE); when(sessionManager.getLoggedInUser((HttpSession) anyObject())).thenReturn(ACCOUNT_JOE.getId()); when(sessionManager.getLoggedInUser((HttpServletRequest) anyObject())).thenReturn( ACCOUNT_JOE.getId()); // Test AccountServiceData requestData = new AccountServiceData(); requestData.email = "joe@email.example.com"; requestData.locale = "es_ES"; requestData.password = "_password_"; requestData.avatarData = IMAGE_BASE64; ByteArrayOutputStream responseStream = new ByteArrayOutputStream(); executeService("/account/joe", "POST", requestData, responseStream, HttpServletResponse.SC_OK); AccountServiceData responseData = (AccountServiceData) ServiceData.fromJson(responseStream.toString("UTF-8"), AccountServiceData.class); assertEquals(requestData.email, responseData.email); assertEquals(requestData.locale, responseData.locale); assertTrue(responseData.avatarUrl.contains("image.png")); } public void testUpdateAccountNotLoggedUser() throws PersistenceException, InvalidParticipantAddress, IOException { // Mock data accountStore.putAccount(ACCOUNT_JOE); when(sessionManager.getLoggedInUser((HttpSession) anyObject())).thenReturn(null); // Test AccountServiceData requestData = new AccountServiceData(); requestData.email = "joe@email.example.com"; requestData.locale = "es_ES"; requestData.password = "_password_"; requestData.avatarData = IMAGE_BASE64; ByteArrayOutputStream responseStream = new ByteArrayOutputStream(); executeService("/account/joe", "POST", requestData, responseStream, HttpServletResponse.SC_FORBIDDEN); } public void testGetAccount() throws InvalidParticipantAddress, PersistenceException, IOException { // Mock data accountStore.putAccount(ACCOUNT_JOE); when(sessionManager.getLoggedInUser((HttpSession) anyObject())).thenReturn(ACCOUNT_JOE.getId()); when(sessionManager.getLoggedInUser((HttpServletRequest) anyObject())).thenReturn( ACCOUNT_JOE.getId()); // Test AccountServiceData requestData = new AccountServiceData(); ByteArrayOutputStream responseStream = new ByteArrayOutputStream(); executeService("/account/joe", "GET", requestData, responseStream, HttpServletResponse.SC_OK); AccountServiceData responseData = (AccountServiceData) ServiceData.fromJson(responseStream.toString("UTF-8"), AccountServiceData.class); assertEquals(ACCOUNT_JOE.getEmail(), responseData.email); assertEquals(ACCOUNT_JOE.getLocale(), responseData.locale); assertTrue(responseData.avatarUrl.contains("image.png")); } public void testGetAccountNotLoggedUser() throws InvalidParticipantAddress, PersistenceException, IOException { // Mock data accountStore.putAccount(ACCOUNT_JOE); when(sessionManager.getLoggedInUser((HttpSession) anyObject())).thenReturn(ACCOUNT_MAT.getId()); when(sessionManager.getLoggedInUser((HttpServletRequest) anyObject())).thenReturn( ACCOUNT_MAT.getId()); // Test AccountServiceData requestData = new AccountServiceData(); ByteArrayOutputStream responseStream = new ByteArrayOutputStream(); executeService("/account/joe", "GET", requestData, responseStream, HttpServletResponse.SC_OK); AccountServiceData responseData = (AccountServiceData) ServiceData.fromJson(responseStream.toString("UTF-8"), AccountServiceData.class); assertNull(responseData.email); assertEquals(ACCOUNT_JOE.getLocale(), responseData.locale); assertTrue(responseData.avatarUrl.contains("image.png")); } public void testGetAccountAvatar() { } public void testQueryAccounts() throws PersistenceException, IOException { // Mock data accountStore.putAccount(ACCOUNT_JOE); accountStore.putAccount(ACCOUNT_TOM); accountStore.putAccount(ACCOUNT_MAT); when(sessionManager.getLoggedInUser((HttpSession) anyObject())).thenReturn(ACCOUNT_MAT.getId()); when(sessionManager.getLoggedInUser((HttpServletRequest) anyObject())).thenReturn( ACCOUNT_MAT.getId()); when(sessionManager.getAllLoggedInUser((HttpServletRequest) anyObject())).thenReturn(CollectionUtils.immutableSet(ACCOUNT_MAT.getId())); // Test AccountServiceData requestData = new AccountServiceData(); ByteArrayOutputStream responseStream = new ByteArrayOutputStream(); executeService("/account", "GET", requestData, responseStream, HttpServletResponse.SC_OK, ImmutableMap.<String, String> of("p", "joe@example.com;tom@example.com;mike@example.com;mat@example.com")); AccountServiceData[] responseData = (AccountServiceData[]) ServiceData.arrayFromJson(responseStream.toString("UTF-8"), AccountServiceData[].class); assertEquals(3, responseData.length); // We expect results in the same order as query assertEqualsAccount(ACCOUNT_JOE, responseData[0]); assertEqualsAccount(ACCOUNT_TOM, responseData[1]); assertEqualsAccount(ACCOUNT_MAT, responseData[2]); } protected void assertEqualsAccount(HumanAccountData expected, AccountServiceData actual) { assertEquals(expected.getId().getAddress(), actual.id); } }