/* * Copyright (c) JForum Team. All rights reserved. * * The software in this package is published under the terms of the LGPL * license a copy of which has been included with this distribution in the * license.txt file. * * The JForum Project * http://www.jforum.net */ package net.jforum.core.support.hibernate; import static org.mockito.Mockito.*; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import net.jforum.actions.helpers.AttachedFile; import net.jforum.entities.Forum; import net.jforum.entities.PollOption; import net.jforum.entities.Post; import net.jforum.entities.Topic; import net.jforum.repository.ConfigRepository; import net.jforum.repository.RankingRepository; import net.jforum.repository.SmilieRepository; import net.jforum.repository.UserRepository; import net.jforum.services.CategoryService; import net.jforum.services.ForumService; import net.jforum.services.GroupService; import net.jforum.services.ModerationService; import net.jforum.services.PostService; import net.jforum.services.TopicService; import org.hibernate.cache.Cache; import org.hibernate.classic.Session; import org.hibernate.engine.SessionFactoryImplementor; import org.junit.Ignore; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.springframework.test.AbstractDependencyInjectionSpringContextTests; /** * @author Rafael Steil, Jonatan Cloutier */ @Ignore("check if this tests are still usefull") @RunWith(MockitoJUnitRunner.class) public class CacheEvictionRulesTestCase extends AbstractDependencyInjectionSpringContextTests { @Mock private SessionFactoryImplementor sessionFactory; /* * **************** * Group Service * **************** */ public void testPermissionsChaged() throws Exception { this.expectQueryCacheEviction("forumDAO.getModerators"); this.executeTargetMethod(GroupService.class, "savePermissions", 0, null); } /* * ************** * Ranking DAO * ************** */ public void testRankingAdded() throws Exception { this.runRankingRepository("add"); } public void testRankingUpdated() throws Exception { this.runRankingRepository("update"); } public void testRankingDeleted() throws Exception { this.runRankingRepository("remove"); } private void runRankingRepository(String methodName) throws Exception { this.expectQueryCacheEviction("rankingDAO"); this.executeTargetMethod(RankingRepository.class, methodName); } /* * ************** * Smilie DAO * ************** */ public void testSmilieAdded() throws Exception { this.runSmilieRepository("add"); } public void testSmilieUpdated() throws Exception { this.runSmilieRepository("update"); } public void testSmilieDeleted() throws Exception { this.runSmilieRepository("remove"); } private void runSmilieRepository(String methodName) throws Exception { this.expectQueryCacheEviction("smilieDAO"); this.executeTargetMethod(SmilieRepository.class, methodName); } /* * *********** * User DAO * *********** */ public void testUserRepositoryAdd() throws Exception { this.expectQueryCacheEviction("userDAO.getTotalUsers"); this.expectQueryCacheEviction("userDAO.getLastRegisteredUser"); this.executeTargetMethod(UserRepository.class, "add"); } /* * ******************* * Config DAO Tests * ******************* */ public void testConfigRepositoryAdd() throws Exception { this.runConfigRepositoryAddOrUpdate("add"); } public void testConfigRepositoryUpdate() throws Exception { this.runConfigRepositoryAddOrUpdate("update"); } private void runConfigRepositoryAddOrUpdate(String methodName) throws Exception { this.expectQueryCacheEviction("configDAO"); this.executeTargetMethod(ConfigRepository.class, methodName); } /* * ************************* * Forum Related Tests * ************************* */ public void testForumServiceAdd() throws Exception { this.runForumServiceTest("add"); } public void testForumServiceUpdate() throws Exception { this.runForumServiceTest("update"); } public void testForumServiceDelete() throws Exception { this.runForumServiceTest("delete"); } public void testForumServiceUpForumOrder() throws Exception { this.runForumServiceTest("upForumOrder"); } public void testForumServiceDownForumOrder() throws Exception { this.runForumServiceTest("downForumOrder"); } private void runForumServiceTest(String methodName) throws Exception { this.expectQueryCacheEviction("categoryDAO.getForums"); this.expect2ndLevelCacheEviction("net.jforum.entities.Forum"); this.executeTargetMethod(ForumService.class, methodName); } /* * ****************** * Posts / Topics * ****************** */ public void testDeletePost() throws Exception { Forum forum = new Forum(); forum.setId(1); Post post = new Post(); post.setForum(forum); this.expectQueryCacheEviction("forumDAO.getTotalMessages"); this.expectQueryCacheEviction("forumDAO.getTotalPosts#" + forum.getId()); this.expectQueryCacheEviction("forumDAO.getTotalTopics#" + forum.getId()); this.expectQueryCacheEviction("recentTopicsDAO"); this.expectQueryCacheEviction("forumDAO.getTopics#" + forum.getId()); this.executeTargetMethod(PostService.class, "delete", post); } public void testTopicDeleted() throws Exception { Topic topic = new Topic(); topic.getForum().setId(1); List<Topic> topics = new ArrayList<Topic>(); topics.add(topic); this.expectQueryCacheEviction("forumDAO.getTotalMessages"); this.expectQueryCacheEviction("forumDAO.getTotalPosts#1"); this.expectQueryCacheEviction("forumDAO.getTotalTopics#1"); this.expectQueryCacheEviction("forumDAO.getTopics#1"); this.expectQueryCacheEviction("rssDAO.getForumTopics#1"); this.expectQueryCacheEviction("recentTopicsDAO"); this.executeVerySpecificTargetMethod(ModerationService.class, "deleteTopics", List.class, topics); } public void testModerationApprovedPost() throws Exception { this.newTopicOrPostCommonAssertions(); Forum forum = new Forum(); forum.setId(1); Topic topic = new Topic(); topic.setPendingModeration(false); topic.setForum(forum); Post post = new Post(); post.setTopic(topic); this.executeTargetMethod(ModerationService.class, "approvePost", post); } public void testModerationTopicMoved() throws Exception { this.expectQueryCacheEviction("forumDAO.getTotalPosts#1"); this.expectQueryCacheEviction("forumDAO.getTotalPosts#2"); this.expectQueryCacheEviction("forumDAO.getTotalTopics#1"); this.expectQueryCacheEviction("forumDAO.getTotalTopics#2"); Session session = mock(Session.class); when(sessionFactory.getCurrentSession()).thenReturn(session); Topic topic = new Topic(); topic.getForum().setId(2); when(session.get(Topic.class, 5)).thenReturn(topic); Cache cache = mock(Cache.class); when(sessionFactory.getSecondLevelCacheRegion("net.jforum.entities.Forum")).thenReturn(cache); this.executeTargetMethod(ModerationService.class, "moveTopics", 1, new int[] { 5 }); verify(cache).remove("net.jforum.entities.Forum#1"); verify(cache).remove("net.jforum.entities.Forum#2"); } public void testTopicServiceAdd() throws Exception { this.runTopicServiceAddOrReply("addTopic"); } public void testTopicServiceReply() throws Exception { this.runTopicServiceAddOrReply("reply"); } private void runTopicServiceAddOrReply(String methodName) throws Exception { this.newTopicOrPostCommonAssertions(); Forum forum = new Forum(); forum.setId(1); Topic topic = new Topic(); topic.setPendingModeration(false); topic.setForum(forum); if ("addTopic".equals(methodName)) { this.executeTargetMethod(TopicService.class, methodName, topic, new ArrayList<PollOption>(), new ArrayList<AttachedFile>()); } else { this.executeTargetMethod(TopicService.class, methodName, topic, new Post(), new ArrayList<AttachedFile>()); } } private void newTopicOrPostCommonAssertions() { this.expectQueryCacheEviction("forumDAO.getTotalPosts#1"); this.expectQueryCacheEviction("forumDAO.getTotalTopics#1"); this.expectQueryCacheEviction("recentTopicsDAO"); this.expectQueryCacheEviction("forumDAO.getTotalMessages"); this.expectQueryCacheEviction("forumDAO.getTopics#1"); } /* * ************************* * Category Related Tets * ************************* */ public void testCategoryServiceAdd() throws Exception { this.runCategoryServiceTest("add"); } public void testCategoryServiceUpdate() throws Exception { this.runCategoryServiceTest("update"); } public void testCategoryServiceDelete() throws Exception { this.runCategoryServiceTest("delete"); } public void testCategoryServiceUpCategoryOrder() throws Exception { this.runCategoryServiceTest("upCategoryOrder"); } public void testCategoryServiceDownCategoryOrder() throws Exception { this.runCategoryServiceTest("downCategoryOrder"); } private void runCategoryServiceTest(String methodName) throws Exception { this.expectQueryCacheEviction("categoryDAO.getAllCategories"); this.expect2ndLevelCacheEviction("net.jforum.entities.Category"); this.executeTargetMethod(CategoryService.class, methodName); } /* * *************************** * General utility methods * *************************** */ private Object getBean(String name) { return this.getApplicationContext().getBean(name); } private void executeTargetMethod(Class<?> entityClass, String methodName, Object... args) throws Exception { Object entity = this.getBean(entityClass.getName()); Set<Method> methods = new HashSet<Method>(Arrays.asList(entityClass.getMethods())); methods.addAll(Arrays.asList(entityClass.getDeclaredMethods())); for (Method method : methods) { if (method.getName().equals(methodName)) { if (args != null && args.length > 0) { method.invoke(entity, args); } else { Class<?>[] parameterTypes = method.getParameterTypes(); if (parameterTypes.length == 1 && parameterTypes[0] == int.class) { //method.setAccessible(true); method.invoke(entity, 0); } else { args = new Object[parameterTypes.length]; //method.setAccessible(true); method.invoke(entity, args); } } } } } private void executeVerySpecificTargetMethod(Class<?> entityClass, String methodName, Class<?> argumentType, Object... args) throws Exception { Object entity = this.getBean(entityClass.getName()); Method method = entity.getClass().getMethod(methodName, argumentType); method.invoke(entity, args); } private void expectQueryCacheEviction(final String regionName) { org.hibernate.cache.QueryCache cache = mock(org.hibernate.cache.QueryCache.class, regionName); when(sessionFactory.getQueryCache(regionName)).thenReturn(cache); verify(cache).clear(); } private void expect2ndLevelCacheEviction(final String regionName) { Cache secondLevelCache = mock(Cache.class, regionName); when(sessionFactory.getSecondLevelCacheRegion(regionName)).thenReturn(secondLevelCache); verify(secondLevelCache).clear(); } /** * @see org.springframework.test.AbstractSingleSpringContextTests#onSetUp() */ @Override protected void onSetUp() throws Exception { super.onSetUp(); Object o = this.getBean("evictionRules"); Field[] fields = o.getClass().getDeclaredFields(); for (Field field : fields) { if (field.getName().equals("factoryImplementor")) { field.setAccessible(true); field.set(o, sessionFactory); } else if (field.getName().equals("sessionFactory")) { field.setAccessible(true); field.set(o, sessionFactory); } } } /** * @see org.springframework.test.AbstractSingleSpringContextTests#getConfigLocations() */ @Override protected String[] getConfigLocations() { return new String[]{ "/cache/cache-eviction-rules-test.xml" }; } }