/* * Copyright (C) 2003-2009 eXo Platform SAS. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see<http://www.gnu.org/licenses/>. */ package org.exoplatform.forum.service.impl; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.util.HashMap; import java.util.Map; import javax.jcr.Node; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.observation.EventListener; import javax.jcr.observation.EventListenerIterator; import javax.jcr.observation.ObservationManager; import org.exoplatform.commons.testing.AssertUtils; import org.exoplatform.commons.testing.KernelUtils; import org.exoplatform.commons.testing.mock.JCRMockUtils; import org.exoplatform.container.component.ComponentPlugin; import org.exoplatform.container.xml.InitParams; import org.exoplatform.forum.common.conf.RoleRulesPlugin; import org.exoplatform.forum.common.jcr.JCRSessionManager; import org.exoplatform.forum.common.jcr.JCRTask; import org.exoplatform.forum.common.jcr.KSDataLocation; import org.exoplatform.forum.common.jcr.KSDataLocation.Locations; import org.exoplatform.forum.membership.AbstractJCRTestCase; import org.exoplatform.forum.service.Category; import org.exoplatform.forum.service.EmailNotifyPlugin; import org.exoplatform.forum.service.Forum; import org.exoplatform.forum.service.ForumAdministration; import org.exoplatform.forum.service.ForumAttachment; import org.exoplatform.forum.service.MessageBuilder; import org.exoplatform.forum.service.Post; import org.exoplatform.forum.service.Topic; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; /** * @author <a href="mailto:patrice.lamarque@exoplatform.com">Patrice Lamarque</a> * @version $Revision$ */ // TODO : // * Fix tests to not have to specify the order of execution like this // * The order of tests execution changed in Junit 4.11 (https://github.com/KentBeck/junit/blob/master/doc/ReleaseNotes4.11.md) @FixMethodOrder(MethodSorters.JVM) public class JCRDataStorageTestCase extends AbstractJCRTestCase { protected Log log = ExoLogger.getLogger(JCRDataStorageTestCase.class); private JCRDataStorage storage; @Override public void beforeRunBare() { try { super.beforeRunBare(); } catch (Exception e) { log.error(e); } } @Override public void setUp() throws Exception { super.setUp(); storage = new JCRDataStorage(); storage.setDataLocator(dataLocation); } @Override public void tearDown() throws Exception { super.tearDown(); } public void testConstructor() { KSDataLocation location = new KSDataLocation("bar"); JCRDataStorage storage = new JCRDataStorage(location); // assertEquals(storage.getRepository(), "foo"); assertEquals(storage.getWorkspace(), "bar"); assertEquals(storage.getPath(), location.getForumHomeLocation()); } public void testPlugins() { KSDataLocation location = new KSDataLocation("bar"); JCRDataStorage storage = new JCRDataStorage(location); storage.getDefaultPlugins(); } public void testUpdateModeratorInForum() throws Exception { String moderatorsPropName = "exo:moderators"; String[] moderators = new String[] { "foo", "zed" }; JCRDataStorage storage = new JCRDataStorage(); Node node = JCRMockUtils.mockNode(); JCRMockUtils.stubProperty(node, moderatorsPropName, "foo", "bar"); String[] actual = storage.updateModeratorInForum(node, moderators); AssertUtils.assertContains(actual, "foo", "bar", "zed"); Node node2 = JCRMockUtils.mockNode(); JCRMockUtils.stubNullProperty(node2, moderatorsPropName); String[] actual2 = storage.updateModeratorInForum(node2, moderators); AssertUtils.assertContains(actual2, "foo", "zed"); Node node3 = JCRMockUtils.mockNode(); JCRMockUtils.stubProperty(node3, moderatorsPropName, " ", "bar"); String[] actual3 = storage.updateModeratorInForum(node3, moderators); AssertUtils.assertContains(actual3, "foo", "zed"); } public void testSetDefaultAvatar() throws Exception { addNode(storage.getDataLocation().getAvatarsLocation()); String avatarLocation = storage.getDataLocation().getAvatarsLocation() + "/username"; assertNodeNotExists(avatarLocation); storage.setDefaultAvatar("username"); assertNodeNotExists(avatarLocation); addFile(avatarLocation); assertNodeExists(avatarLocation); storage.setDefaultAvatar("username"); assertNodeNotExists(avatarLocation); } public void testGetAvatar() throws Exception { String avatarLocation = storage.getDataLocation().getAvatarsLocation() + "/username2"; // assertNull(storage.getUserAvatar("username2")); addFile(avatarLocation); ForumAttachment attachment = storage.getUserAvatar("username2"); assertNotNull(attachment); assertEquals("avatar.plain", attachment.getName()); assertEquals("text/plain", attachment.getMimeType()); assertEquals("/" + getWorkspace() + "/" + avatarLocation, attachment.getPath()); // /portal-test/ksUserAvatar/username assertEquals("stuff", stringOf(attachment.getInputStream())); } public void testSaveAvatar() throws Exception { String avatarLocation = storage.getDataLocation().getAvatarsLocation() + "/username3"; assertNull(storage.getUserAvatar("username3")); addFile(avatarLocation); storage.saveUserAvatar("username3", new TextForumAttachment("updated content")); Node node = getNode(avatarLocation); assertEquals("updated content", stringOf(node.getNode("jcr:content").getProperty("jcr:data").getStream())); } public void testAddPlugin() throws Exception { // fixture addNode(storage.getDataLocation().getForumCategoriesLocation(), "exo:categoryHome"); // null plugin storage.addPlugin(null); assertNull(storage.getServerConfig().get("foo")); // not EmailNotifyPlugin ComponentPlugin plugin = mock(ComponentPlugin.class); storage.addPlugin(plugin); assertNull(storage.getServerConfig().get("foo")); // with EmailNotifyPlugin InitParams params = new InitParams(); Map<String, String> map = new HashMap<String, String>(); map.put("foo", "bar"); KernelUtils.addPropertiesParam(params, "email.configuration.info", map); EmailNotifyPlugin notifPlugin = new EmailNotifyPlugin(params); storage.addPlugin(notifPlugin); assertEquals("bar", storage.getServerConfig().get("foo")); } public void testAddRolePlugin() throws Exception { storage.addRolePlugin(null); AssertUtils.assertEmpty(storage.getRulesPlugins()); // not RoleRulesPlugin ComponentPlugin plugin = mock(ComponentPlugin.class); storage.addRolePlugin(plugin); AssertUtils.assertEmpty(storage.getRulesPlugins()); InitParams params = new InitParams(); KernelUtils.addValueParam(params, "role", "ADMIN"); KernelUtils.addValuesParam(params, "rules", "rule1", "rule2"); storage.addRolePlugin(new RoleRulesPlugin(params)); AssertUtils.assertNotEmpty(storage.getRulesPlugins()); } private <T extends EventListener> boolean hasListenerOfType(ObservationManager manager, Class<T> clazz) throws RepositoryException { EventListenerIterator it = manager.getRegisteredEventListeners(); boolean found = false; while (it.hasNext()) { EventListener listener = it.nextEventListener(); if (listener.getClass() == clazz) { found = true; break; } } return found; } public void testSaveForumAdministration() throws Exception { adminNodeFixture(); // test create ForumAdministration admin = new ForumAdministration(); admin.setCensoredKeyword("4letterword"); admin.setEnableHeaderSubject(true); admin.setForumSortBy("name"); admin.setForumSortByType("descending"); admin.setHeaderSubject("header"); admin.setNotifyEmailContent("content"); admin.setNotifyEmailMoved("moved"); admin.setTopicSortBy("postCount"); admin.setTopicSortByType("ascending"); storage.saveForumAdministration(admin); assertAdminSaved(admin); // test update admin.setCensoredKeyword("censored"); admin.setEnableHeaderSubject(false); admin.setForumSortBy("forum"); admin.setForumSortByType("ascending"); admin.setHeaderSubject("subject"); admin.setNotifyEmailContent("c"); admin.setNotifyEmailMoved("m"); admin.setTopicSortBy("topic"); admin.setTopicSortByType("descending"); storage.saveForumAdministration(admin); assertAdminSaved(admin); } public void testGetForumAdministration() throws Exception { // fixture String adminPath = adminNodeFixture(); Session session = getSession(); Node adminNode = session.getRootNode().getNode(adminPath); adminNode.setProperty("exo:forumSortBy", "a"); adminNode.setProperty("exo:forumSortByType", "b"); adminNode.setProperty("exo:topicSortBy", "c"); adminNode.setProperty("exo:topicSortByType", "d"); adminNode.setProperty("exo:censoredKeyword", "e"); adminNode.setProperty("exo:enableHeaderSubject", true); adminNode.setProperty("exo:headerSubject", "f"); adminNode.setProperty("exo:notifyEmailContent", "g"); adminNode.setProperty("exo:notifyEmailMoved", "h"); session.save(); // call method and check values ForumAdministration admin = storage.getForumAdministration(); assertEquals("a", admin.getForumSortBy()); assertEquals("b", admin.getForumSortByType()); assertEquals("c", admin.getTopicSortBy()); assertEquals("d", admin.getTopicSortByType()); assertEquals("e", admin.getCensoredKeyword()); assertEquals(true, admin.getEnableHeaderSubject()); assertEquals("f", admin.getHeaderSubject()); assertEquals("g", admin.getNotifyEmailContent()); assertEquals("h", admin.getNotifyEmailMoved()); } public void testUpdatePostCount() throws Exception { // initDefaultData(); // default data Forum forum = storage.getForum(categoryId, forumId); assertNotNull(forum); assertEquals(1, forum.getPostCount()); // Test auto update by JCR listener Topic topic = createdTopic(USER_DEMO); storage.saveTopic(categoryId, forumId, topic, true, false, new MessageBuilder()); assertEquals(2, storage.getForum(categoryId, forumId).getPostCount()); assertEquals(1, storage.getUserInfo(USER_ROOT).getTotalPost()); // add more 3 posts storage.savePost(categoryId, forumId, topic.getId(), createdPost(), true, new MessageBuilder()); storage.savePost(categoryId, forumId, topic.getId(), createdPost(), true, new MessageBuilder()); storage.savePost(categoryId, forumId, topic.getId(), createdPost(), true, new MessageBuilder()); // assertEquals(5, storage.getForum(categoryId, forumId).getPostCount()); assertEquals(3, storage.getTopic(categoryId, forumId, topic.getId(), "").getPostCount()); assertEquals(4, storage.getUserInfo(USER_ROOT).getTotalPost()); // manual call JCRDataStorage#updatePostCount // save new post on default topic Post p = createdPost(); storage.savePost(categoryId, forumId, topicId, p, true, new MessageBuilder()); assertEquals(6, storage.getForum(categoryId, forumId).getPostCount()); assertEquals(1, storage.getTopic(categoryId, forumId, topicId, "").getPostCount()); assertEquals(5, storage.getUserInfo(USER_ROOT).getTotalPost()); // for (int i = 0; i < 3; i++) { storage.updatePostCount(p.getPath(), USER_ROOT); } assertEquals(9, storage.getForum(categoryId, forumId).getPostCount()); assertEquals(4, storage.getTopic(categoryId, forumId, topicId, "").getPostCount()); // method JCRDataStorage#updatePostCount() can not update user profile assertEquals(5, storage.getUserInfo(USER_ROOT).getTotalPost()); } private String adminNodeFixture() throws Exception { String adminPath = storage.getDataLocation().getAdministrationLocation(); if (!getSession().getRootNode().hasNode(adminPath)) { addNode(adminPath, "exo:administrationHome"); } adminPath += "/forumAdministration"; addNode(adminPath, "exo:administration"); return adminPath; } private void assertAdminSaved(ForumAdministration admin) { String adminPath = storage.getDataLocation().getAdministrationLocation() + "/forumAdministration"; assertNodeExists(adminPath); Node adminNode = getNode(adminPath); assertPropertyEquals(admin.getForumSortBy(), adminNode, "exo:forumSortBy"); assertPropertyEquals(admin.getForumSortByType(), adminNode, "exo:forumSortByType"); assertPropertyEquals(admin.getTopicSortBy(), adminNode, "exo:topicSortBy"); assertPropertyEquals(admin.getTopicSortByType(), adminNode, "exo:topicSortByType"); assertPropertyEquals(admin.getCensoredKeyword(), adminNode, "exo:censoredKeyword"); assertPropertyEquals(admin.getEnableHeaderSubject(), adminNode, "exo:enableHeaderSubject"); assertPropertyEquals(admin.getHeaderSubject(), adminNode, "exo:headerSubject"); assertPropertyEquals(admin.getNotifyEmailContent(), adminNode, "exo:notifyEmailContent"); assertPropertyEquals(admin.getNotifyEmailMoved(), adminNode, "exo:notifyEmailMoved"); } static class TextForumAttachment extends ForumAttachment { private String text; public TextForumAttachment(String content) { this.text = content; setMimeType("text/plain"); super.setSize(content.getBytes().length); } @Override public InputStream getInputStream() throws Exception { return new ByteArrayInputStream(text.getBytes("UTF-8")); } } private String stringOf(InputStream inputStream) { try { return new BufferedReader(new InputStreamReader(inputStream, "UTF-8")).readLine(); } catch (Exception e) { throw new RuntimeException(e); } } public void _testDefaultAvatarWithMocks() throws Exception { JCRDataStorage storage = new JCRDataStorage(); KSDataLocation locator = new KSDataLocation("wp"); JCRSessionManager sessionManager = stubJCRSessionManager(); locator.setSessionManager(sessionManager); storage.setDataLocator(locator); Node avatarHome = stubNodeForPath(Locations.KS_USER_AVATAR, sessionManager); storage.setDefaultAvatar("foo"); verify(avatarHome).hasNode("foo"); // verify we tried to load the node Node avatar = stubChild(avatarHome, "foo", "nt:file"); storage.setDefaultAvatar("foo"); verify(avatar).remove(); verify(avatarHome).save(); } @SuppressWarnings("unchecked") private JCRSessionManager stubJCRSessionManager() { JCRSessionManager sessionManager = mock(JCRSessionManager.class); when(sessionManager.executeAndSave(any(JCRTask.class))).thenCallRealMethod(); when(sessionManager.execute(any(JCRTask.class))).thenCallRealMethod(); return sessionManager; } private Node stubChild(Node parent, String name, String type) throws Exception { Node child = mock(Node.class); when(child.isNodeType(type)).thenReturn(true); when(child.getName()).thenReturn(name); when(parent.getNode(name)).thenReturn(child); when(parent.hasNode(name)).thenReturn(true); return child; } private Node stubNodeForPath(String path, JCRSessionManager manager) throws Exception { Node node = mock(Node.class); Node root = mock(Node.class); when(root.getNode(path)).thenReturn(node); Session session = mock(Session.class); when(session.getRootNode()).thenReturn(root); when(manager.createSession()).thenReturn(session); when(manager.openSession()).thenReturn(session); when(manager.getCurrentSession()).thenReturn(session); return node; } }