diff --git a/source/java/org/alfresco/repo/rating/RatingServiceIntegrationTest.java b/source/java/org/alfresco/repo/rating/RatingServiceIntegrationTest.java index c75e5d1987..9c36f614db 100644 --- a/source/java/org/alfresco/repo/rating/RatingServiceIntegrationTest.java +++ b/source/java/org/alfresco/repo/rating/RatingServiceIntegrationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2011 Alfresco Software Limited. + * Copyright (C) 2005-2012 Alfresco Software Limited. * * This file is part of Alfresco * @@ -19,6 +19,12 @@ package org.alfresco.repo.rating; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import java.util.Date; import java.util.HashMap; import java.util.List; @@ -28,40 +34,65 @@ import org.alfresco.model.ContentModel; import org.alfresco.repo.jscript.ClasspathScriptLocation; import org.alfresco.repo.model.Repository; import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.service.cmr.rating.Rating; import org.alfresco.service.cmr.rating.RatingScheme; import org.alfresco.service.cmr.rating.RatingService; import org.alfresco.service.cmr.rating.RatingServiceException; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.ScriptLocation; import org.alfresco.service.cmr.repository.ScriptService; -import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.RegexQNamePattern; -import org.alfresco.util.BaseAlfrescoSpringTest; -import org.alfresco.util.PropertyMap; +import org.alfresco.util.test.junitrules.AlfrescoPerson; +import org.alfresco.util.test.junitrules.ApplicationContextInit; +import org.alfresco.util.test.junitrules.TemporaryNodes; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.RuleChain; /** * @author Neil McErlean * @since 3.4 */ -public class RatingServiceIntegrationTest extends BaseAlfrescoSpringTest +public class RatingServiceIntegrationTest { - private static final String USER_ONE = "UserOne"; - private static final String USER_TWO = "UserTwo"; -// private CopyService copyService; - private PersonService personService; - private RatingService ratingService; - private Repository repositoryHelper; - private ScriptService scriptService; - private RatingNamingConventionsUtil ratingNamingConventions; + // Rule to initialise the default Alfresco spring configuration + public static ApplicationContextInit APP_CONTEXT_INIT = new ApplicationContextInit(); - private NodeRef companyHome; + // Rules to create 2 test users. + public static AlfrescoPerson TEST_USER1 = new AlfrescoPerson(APP_CONTEXT_INIT, "UserOne"); + public static AlfrescoPerson TEST_USER2 = new AlfrescoPerson(APP_CONTEXT_INIT, "UserTwo"); + + // A rule to manage test nodes reused across all the test methods + public static TemporaryNodes STATIC_TEST_NODES = new TemporaryNodes(APP_CONTEXT_INIT); + + // Tie them together in a static Rule Chain + @ClassRule public static RuleChain ruleChain = RuleChain.outerRule(APP_CONTEXT_INIT) + .around(TEST_USER1) + .around(TEST_USER2) + .around(STATIC_TEST_NODES); + + // A rule to manage test nodes use in each test method + @Rule public TemporaryNodes testNodes = new TemporaryNodes(APP_CONTEXT_INIT); + + // Various services + private static NodeService NODE_SERVICE; + private static RatingService RATING_SERVICE; + private static RetryingTransactionHelper TRANSACTION_HELPER; + private static ScriptService SCRIPT_SERVICE; + private static RatingNamingConventionsUtil RATING_NAMING_CONVENTIONS; + + private static NodeRef COMPANY_HOME; // These NodeRefs are used by the test methods. - private NodeRef testFolder; -// private NodeRef testFolderCopyDest; + private static NodeRef TEST_FOLDER; private NodeRef testDoc_Admin; private NodeRef testDoc_UserOne; private NodeRef testDoc_UserTwo; @@ -70,55 +101,37 @@ public class RatingServiceIntegrationTest extends BaseAlfrescoSpringTest private static final String LIKES_SCHEME_NAME = "likesRatingScheme"; private static final String FIVE_STAR_SCHEME_NAME = "fiveStarRatingScheme"; - @SuppressWarnings("deprecation") - @Override - protected void onSetUpInTransaction() throws Exception + @BeforeClass public static void initStaticData() throws Exception { - super.onSetUpInTransaction(); -// this.copyService = (CopyService)this.applicationContext.getBean("CopyService"); - this.personService = (PersonService)this.applicationContext.getBean("PersonService"); - this.ratingService = (RatingService) this.applicationContext.getBean("ratingService"); - this.repositoryHelper = (Repository) this.applicationContext.getBean("repositoryHelper"); -// this.transactionHelper = (RetryingTransactionHelper) this.applicationContext.getBean("retryingTransactionHelper"); - this.scriptService = (ScriptService) this.applicationContext.getBean("scriptService"); - this.ratingNamingConventions = (RatingNamingConventionsUtil)this.applicationContext.getBean("rollupNamingConventions"); + NODE_SERVICE = (NodeService) APP_CONTEXT_INIT.getApplicationContext().getBean("nodeService"); + RATING_NAMING_CONVENTIONS = (RatingNamingConventionsUtil) APP_CONTEXT_INIT.getApplicationContext().getBean("rollupNamingConventions"); + RATING_SERVICE = (RatingService) APP_CONTEXT_INIT.getApplicationContext().getBean("ratingService"); + SCRIPT_SERVICE = (ScriptService) APP_CONTEXT_INIT.getApplicationContext().getBean("scriptService"); + TRANSACTION_HELPER = (RetryingTransactionHelper) APP_CONTEXT_INIT.getApplicationContext().getBean("retryingTransactionHelper"); + + Repository repositoryHelper = (Repository) APP_CONTEXT_INIT.getApplicationContext().getBean("repositoryHelper"); + COMPANY_HOME = repositoryHelper.getCompanyHome(); + + // Create some static test content + TEST_FOLDER = STATIC_TEST_NODES.createNode(COMPANY_HOME, "testFolder", ContentModel.TYPE_FOLDER, AuthenticationUtil.getAdminUserName()); - // Set the current security context as admin - AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); - - companyHome = this.repositoryHelper.getCompanyHome(); - - testFolder = createNode(companyHome, "testFolder", ContentModel.TYPE_FOLDER); -// testFolderCopyDest = createNode(companyHome, "testFolderCopyDest", ContentModel.TYPE_FOLDER); - testDoc_Admin = createNode(testFolder, "testDocInFolder", ContentModel.TYPE_CONTENT); - - createUser(USER_ONE); - createUser(USER_TWO); - - AuthenticationUtil.setFullyAuthenticatedUser(USER_TWO); - testDoc_UserOne = createNode(testFolder, "userOnesDoc", ContentModel.TYPE_CONTENT); - AuthenticationUtil.setFullyAuthenticatedUser(USER_ONE); - testDoc_UserTwo = createNode(testFolder, "userTwosDoc", ContentModel.TYPE_CONTENT); - - // And back to admin - AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); } - @Override - protected void onTearDownInTransaction() throws Exception + @Before public void createTestContent() { - AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); - deleteUser(USER_TWO); - deleteUser(USER_ONE); + // Create some test content + testDoc_Admin = testNodes.createNode(TEST_FOLDER, "testDocInFolder", ContentModel.TYPE_CONTENT, AuthenticationUtil.getAdminUserName()); + testDoc_UserOne = testNodes.createNode(TEST_FOLDER, "userOnesDoc", ContentModel.TYPE_CONTENT, TEST_USER1.getUsername()); + testDoc_UserTwo = testNodes.createNode(TEST_FOLDER, "userTwosDoc", ContentModel.TYPE_CONTENT, TEST_USER2.getUsername()); } /** * This method tests that the expected 'out of the box' rating schemes are available * and correctly initialised. */ - public void testOutOfTheBoxRatingSchemes() throws Exception + @Test public void outOfTheBoxRatingSchemes() throws Exception { - Map schemes = this.ratingService.getRatingSchemes(); + Map schemes = RATING_SERVICE.getRatingSchemes(); assertNotNull("rating scheme collection was null.", schemes); assertTrue("rating scheme collection was empty.", schemes.isEmpty() == false); @@ -126,22 +139,24 @@ public class RatingServiceIntegrationTest extends BaseAlfrescoSpringTest RatingScheme likesRS = schemes.get(LIKES_SCHEME_NAME); assertNotNull("'likes' rating scheme was missing.", likesRS); assertEquals("'likes' rating scheme had wrong name.", LIKES_SCHEME_NAME, likesRS.getName()); - assertEquals("'likes' rating scheme had wrong min.", 1.0f, likesRS.getMinRating()); - assertEquals("'likes' rating scheme had wrong max.", 1.0f, likesRS.getMaxRating()); + assertEquals("'likes' rating scheme had wrong min.", 1, (int)likesRS.getMinRating()); + assertEquals("'likes' rating scheme had wrong max.", 1, (int)likesRS.getMaxRating()); RatingScheme fiveStarRS = schemes.get(FIVE_STAR_SCHEME_NAME); assertNotNull("'5*' rating scheme was missing.", fiveStarRS); assertEquals("'5*' rating scheme had wrong name.", FIVE_STAR_SCHEME_NAME, fiveStarRS.getName()); - assertEquals("'5*' rating scheme had wrong min.", 1.0f, fiveStarRS.getMinRating()); - assertEquals("'5*' rating scheme had wrong max.", 5.0f, fiveStarRS.getMaxRating()); + assertEquals("'5*' rating scheme had wrong min.", 1, (int)fiveStarRS.getMinRating()); + assertEquals("'5*' rating scheme had wrong max.", 5, (int)fiveStarRS.getMaxRating()); } /** * This test method ensures that an attempt to apply an out-of-range rating value * throws the expected exception. */ - public void testApplyIllegalRatings() throws Exception + @Test public void applyIllegalRatings() throws Exception { + AuthenticationUtil.setFullyAuthenticatedUser(TEST_USER1.getUsername()); + // See rating-services-context.xml for definitions of these rating schemes. float[] illegalRatings = new float[]{0.0f, 2.0f}; for (float illegalRating : illegalRatings) @@ -154,7 +169,7 @@ public class RatingServiceIntegrationTest extends BaseAlfrescoSpringTest { try { - ratingService.applyRating(nodeRef, illegalRating, schemeName); + RATING_SERVICE.applyRating(nodeRef, illegalRating, schemeName); } catch (RatingServiceException expectedException) { @@ -163,142 +178,151 @@ public class RatingServiceIntegrationTest extends BaseAlfrescoSpringTest fail("Illegal rating " + illegalRating + " should have caused exception."); } - public void testApplyUpdateDeleteRatings() throws Exception + @Test public void applyUpdateDeleteRatings() throws Exception { - // We'll do all this as user 'UserOne'. - AuthenticationUtil.setFullyAuthenticatedUser(USER_TWO); - - //Before we start, let's ensure the read behaviour on a pristine node is correct. - Rating nullRating = ratingService.getRatingByCurrentUser(testDoc_Admin, LIKES_SCHEME_NAME); - assertNull("Expected a null rating,", nullRating); - assertNull("Expected a null remove result.", ratingService.removeRatingByCurrentUser(testDoc_Admin, LIKES_SCHEME_NAME)); - - final float fiveStarScore = 5; - - ratingService.applyRating(testDoc_Admin, fiveStarScore, FIVE_STAR_SCHEME_NAME); - assertModifierIs(testDoc_Admin, AuthenticationUtil.getAdminUserName()); - - // Some basic node structure tests. - assertTrue(ContentModel.ASPECT_RATEABLE + " aspect missing.", - nodeService.hasAspect(testDoc_Admin, ContentModel.ASPECT_RATEABLE)); - - List allChildren = nodeService.getChildAssocs(testDoc_Admin, - ContentModel.ASSOC_RATINGS, RegexQNamePattern.MATCH_ALL); - - // It's one cm:rating node per user - assertEquals("Wrong number of ratings nodes.", 1, allChildren.size()); - // child-assoc of type cm:ratings - assertEquals("Wrong type qname on ratings assoc", ContentModel.ASSOC_RATINGS, allChildren.get(0).getTypeQName()); - // child-assoc of name cm: - QName expectedAssocName = ratingNamingConventions.getRatingAssocNameFor(AuthenticationUtil.getFullyAuthenticatedUser(), FIVE_STAR_SCHEME_NAME); - assertEquals("Wrong qname on ratings assoc", expectedAssocName, allChildren.get(0).getQName()); - // node structure seems ok. - - - // Now to check the persisted ratings data are ok. - Rating fiveStarRating = ratingService.getRatingByCurrentUser(testDoc_Admin, FIVE_STAR_SCHEME_NAME); - - assertNotNull("'5*' rating was null.", fiveStarRating); - assertEquals("Wrong score for rating", fiveStarScore, fiveStarRating.getScore()); - assertEquals("Wrong user for rating", AuthenticationUtil.getFullyAuthenticatedUser(), fiveStarRating.getAppliedBy()); - final Date fiveStarRatingAppliedAt = fiveStarRating.getAppliedAt(); - assertDateIsCloseToNow(fiveStarRatingAppliedAt); - - // Now we'll update a rating - final float updatedFiveStarScore = 3; - ratingService.applyRating(testDoc_Admin, updatedFiveStarScore, FIVE_STAR_SCHEME_NAME); - assertModifierIs(testDoc_Admin, AuthenticationUtil.getAdminUserName()); - - // Some basic node structure tests. - allChildren = nodeService.getChildAssocs(testDoc_Admin, - ContentModel.ASSOC_RATINGS, RegexQNamePattern.MATCH_ALL); - - // Still one cm:rating node - assertEquals("Wrong number of ratings nodes.", 1, allChildren.size()); - // Same assoc names - assertEquals("Wrong type qname on ratings assoc", ContentModel.ASSOC_RATINGS, allChildren.get(0).getTypeQName()); - assertEquals("Wrong qname on ratings assoc", expectedAssocName, allChildren.get(0).getQName()); - // node structure seems ok. - - - // Now to check the updated ratings data are ok. - Rating updatedFiveStarRating = ratingService.getRatingByCurrentUser(testDoc_Admin, FIVE_STAR_SCHEME_NAME); - - // 'five star' data should be changed - new score, new date - assertNotNull("'5*' rating was null.", updatedFiveStarRating); - assertEquals("Wrong score for rating", updatedFiveStarScore, updatedFiveStarRating.getScore()); - assertEquals("Wrong user for rating", AuthenticationUtil.getFullyAuthenticatedUser(), updatedFiveStarRating.getAppliedBy()); - assertTrue("five star rating date was unchanged.", fiveStarRatingAppliedAt.equals(updatedFiveStarRating.getAppliedAt()) == false); - assertDateIsCloseToNow(updatedFiveStarRating.getAppliedAt()); - - // And delete the 'five star' rating. - Rating deletedStarRating = ratingService.removeRatingByCurrentUser(testDoc_Admin, FIVE_STAR_SCHEME_NAME); - assertModifierIs(testDoc_Admin, AuthenticationUtil.getAdminUserName()); - // 'five star' rating data should be unchanged. - assertNotNull("'5*' rating was null.", deletedStarRating); - assertEquals("Wrong score for rating", updatedFiveStarScore, deletedStarRating.getScore()); - assertEquals("Wrong user for rating", AuthenticationUtil.getFullyAuthenticatedUser(), deletedStarRating.getAppliedBy()); - assertEquals("Wrong date for rating", updatedFiveStarRating.getAppliedAt(), deletedStarRating.getAppliedAt()); - - // And the deleted ratings should be gone. - assertNull("5* rating not null.", ratingService.getRatingByCurrentUser(testDoc_Admin, FIVE_STAR_SCHEME_NAME)); + TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback() + { + public Void execute() throws Throwable + { + // We'll do all this as user 'UserTwo'. + AuthenticationUtil.setFullyAuthenticatedUser(TEST_USER2.getUsername()); + + //Before we start, let's ensure the read behaviour on a pristine node is correct. + Rating nullRating = RATING_SERVICE.getRatingByCurrentUser(testDoc_Admin, LIKES_SCHEME_NAME); + assertNull("Expected a null rating,", nullRating); + assertNull("Expected a null remove result.", RATING_SERVICE.removeRatingByCurrentUser(testDoc_Admin, LIKES_SCHEME_NAME)); + + final int fiveStarScore = 5; + + RATING_SERVICE.applyRating(testDoc_Admin, fiveStarScore, FIVE_STAR_SCHEME_NAME); + assertModifierIs(testDoc_Admin, AuthenticationUtil.getAdminUserName()); + + // Some basic node structure tests. + assertTrue(ContentModel.ASPECT_RATEABLE + " aspect missing.", + NODE_SERVICE.hasAspect(testDoc_Admin, ContentModel.ASPECT_RATEABLE)); + + List allChildren = NODE_SERVICE.getChildAssocs(testDoc_Admin, + ContentModel.ASSOC_RATINGS, RegexQNamePattern.MATCH_ALL); + + // It's one cm:rating node per user + assertEquals("Wrong number of ratings nodes.", 1, allChildren.size()); + // child-assoc of type cm:ratings + assertEquals("Wrong type qname on ratings assoc", ContentModel.ASSOC_RATINGS, allChildren.get(0).getTypeQName()); + // child-assoc of name cm: + QName expectedAssocName = RATING_NAMING_CONVENTIONS.getRatingAssocNameFor(AuthenticationUtil.getFullyAuthenticatedUser(), FIVE_STAR_SCHEME_NAME); + assertEquals("Wrong qname on ratings assoc", expectedAssocName, allChildren.get(0).getQName()); + // node structure seems ok. + + + // Now to check the persisted ratings data are ok. + Rating fiveStarRating = RATING_SERVICE.getRatingByCurrentUser(testDoc_Admin, FIVE_STAR_SCHEME_NAME); + + assertNotNull("'5*' rating was null.", fiveStarRating); + assertEquals("Wrong score for rating", fiveStarScore, (int)fiveStarRating.getScore()); + assertEquals("Wrong user for rating", AuthenticationUtil.getFullyAuthenticatedUser(), fiveStarRating.getAppliedBy()); + final Date fiveStarRatingAppliedAt = fiveStarRating.getAppliedAt(); + + // Now we'll update a rating + final int updatedFiveStarScore = 3; + RATING_SERVICE.applyRating(testDoc_Admin, updatedFiveStarScore, FIVE_STAR_SCHEME_NAME); + assertModifierIs(testDoc_Admin, AuthenticationUtil.getAdminUserName()); + + // Some basic node structure tests. + allChildren = NODE_SERVICE.getChildAssocs(testDoc_Admin, + ContentModel.ASSOC_RATINGS, RegexQNamePattern.MATCH_ALL); + + // Still one cm:rating node + assertEquals("Wrong number of ratings nodes.", 1, allChildren.size()); + // Same assoc names + assertEquals("Wrong type qname on ratings assoc", ContentModel.ASSOC_RATINGS, allChildren.get(0).getTypeQName()); + assertEquals("Wrong qname on ratings assoc", expectedAssocName, allChildren.get(0).getQName()); + // node structure seems ok. + + + // Now to check the updated ratings data are ok. + Rating updatedFiveStarRating = RATING_SERVICE.getRatingByCurrentUser(testDoc_Admin, FIVE_STAR_SCHEME_NAME); + + // 'five star' data should be changed - new score, new date + assertNotNull("'5*' rating was null.", updatedFiveStarRating); + assertEquals("Wrong score for rating", updatedFiveStarScore, (int)updatedFiveStarRating.getScore()); + assertEquals("Wrong user for rating", AuthenticationUtil.getFullyAuthenticatedUser(), updatedFiveStarRating.getAppliedBy()); + assertTrue("five star rating date was unchanged.", fiveStarRatingAppliedAt.equals(updatedFiveStarRating.getAppliedAt()) == false); + + // And delete the 'five star' rating. + Rating deletedStarRating = RATING_SERVICE.removeRatingByCurrentUser(testDoc_Admin, FIVE_STAR_SCHEME_NAME); + assertModifierIs(testDoc_Admin, AuthenticationUtil.getAdminUserName()); + // 'five star' rating data should be unchanged. + assertNotNull("'5*' rating was null.", deletedStarRating); + assertEquals("Wrong score for rating", updatedFiveStarScore, (int)deletedStarRating.getScore()); + assertEquals("Wrong user for rating", AuthenticationUtil.getFullyAuthenticatedUser(), deletedStarRating.getAppliedBy()); + assertEquals("Wrong date for rating", updatedFiveStarRating.getAppliedAt(), deletedStarRating.getAppliedAt()); + + // And the deleted ratings should be gone. + assertNull("5* rating not null.", RATING_SERVICE.getRatingByCurrentUser(testDoc_Admin, FIVE_STAR_SCHEME_NAME)); + + return null; + } + }); } - /** - * This test method asserts that the specified date is effectively equal to now. - * We can't assert that the two dates are exactly equal but we do assert that - * they are equal to within a specified tolerance. - * @param d the date to check - */ - private void assertDateIsCloseToNow(Date d) + @Test public void oneUserRatesAndRerates() throws Exception { -// assertNotNull("Date was unexpectedly null", d); -// Date now = new Date(); -// assertTrue("Date was not before 'now'", now.after(d)); -// final long millisTolerance = 5000l; // 5 seconds -// assertTrue("Date was not within " + millisTolerance + "ms of 'now'.", now.getTime() - d.getTime() < millisTolerance); - } - - public void testOneUserRatesAndRerates() throws Exception - { - AuthenticationUtil.setFullyAuthenticatedUser(USER_ONE); - ratingService.applyRating(testDoc_Admin, 1.0f, FIVE_STAR_SCHEME_NAME); - - // A new score in the same rating scheme by the same user should replace the previous score. - ratingService.applyRating(testDoc_Admin, 2.0f, FIVE_STAR_SCHEME_NAME); - - float meanRating = ratingService.getAverageRating(testDoc_Admin, FIVE_STAR_SCHEME_NAME); - assertEquals("Document had wrong mean rating.", 2f, meanRating); - - float totalRating = ratingService.getTotalRating(testDoc_Admin, FIVE_STAR_SCHEME_NAME); - assertEquals("Document had wrong total rating.", 2.0f, totalRating); - - int ratingsCount = ratingService.getRatingsCount(testDoc_Admin, FIVE_STAR_SCHEME_NAME); - assertEquals("Document had wrong ratings count.", 1, ratingsCount); - - // There should only be one rating child node under the rated node. - assertEquals("Wrong number of child nodes", 1 , nodeService.getChildAssocs(testDoc_Admin).size()); + TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback() + { + public Void execute() throws Throwable + { + AuthenticationUtil.setFullyAuthenticatedUser(TEST_USER1.getUsername()); + RATING_SERVICE.applyRating(testDoc_Admin, 1.0f, FIVE_STAR_SCHEME_NAME); + + // A new score in the same rating scheme by the same user should replace the previous score. + RATING_SERVICE.applyRating(testDoc_Admin, 2.0f, FIVE_STAR_SCHEME_NAME); + + float meanRating = RATING_SERVICE.getAverageRating(testDoc_Admin, FIVE_STAR_SCHEME_NAME); + assertEquals("Document had wrong mean rating.", 2, (int)meanRating); + + float totalRating = RATING_SERVICE.getTotalRating(testDoc_Admin, FIVE_STAR_SCHEME_NAME); + assertEquals("Document had wrong total rating.", 2, (int)totalRating); + + int ratingsCount = RATING_SERVICE.getRatingsCount(testDoc_Admin, FIVE_STAR_SCHEME_NAME); + assertEquals("Document had wrong ratings count.", 1, ratingsCount); + + // There should only be one rating child node under the rated node. + assertEquals("Wrong number of child nodes", 1 , NODE_SERVICE.getChildAssocs(testDoc_Admin).size()); + + return null; + } + }); } /** * This test method ensures that if a single user attempts to rate a piece of content in two * different rating schemes, then an exception should not be thrown. */ - public void testOneUserRatesInTwoSchemes() throws Exception + @Test public void oneUserRatesInTwoSchemes() throws Exception { - AuthenticationUtil.setFullyAuthenticatedUser(USER_ONE); - ratingService.applyRating(testDoc_Admin, 2.0f, FIVE_STAR_SCHEME_NAME); - - // A new score in a different rating scheme by the same user should not fail. - ratingService.applyRating(testDoc_Admin, 1.0f, LIKES_SCHEME_NAME); + AuthenticationUtil.setFullyAuthenticatedUser(TEST_USER1.getUsername()); - // There should be two rating child nodes under the rated node. - assertEquals("Wrong number of child nodes", 2 , nodeService.getChildAssocs(testDoc_Admin).size()); - - List ratings = ratingService.getRatingsByCurrentUser(testDoc_Admin); - assertEquals(2, ratings.size()); - assertEquals(FIVE_STAR_SCHEME_NAME, ratings.get(0).getScheme().getName()); - assertEquals(LIKES_SCHEME_NAME, ratings.get(1).getScheme().getName()); + TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback() + { + public Void execute() throws Throwable + { + + RATING_SERVICE.applyRating(testDoc_UserTwo, 2.0f, FIVE_STAR_SCHEME_NAME); + + // A new score in a different rating scheme by the same user should not fail. + RATING_SERVICE.applyRating(testDoc_UserTwo, 1.0f, LIKES_SCHEME_NAME); + + // There should be two rating child nodes under the rated node. + assertEquals("Wrong number of child nodes", 2 , NODE_SERVICE.getChildAssocs(testDoc_UserTwo).size()); + + List ratings = RATING_SERVICE.getRatingsByCurrentUser(testDoc_UserTwo); + assertEquals(2, ratings.size()); + assertEquals(FIVE_STAR_SCHEME_NAME, ratings.get(0).getScheme().getName()); + assertEquals(LIKES_SCHEME_NAME, ratings.get(1).getScheme().getName()); + + return null; + } + }); } /** @@ -306,43 +330,51 @@ public class RatingServiceIntegrationTest extends BaseAlfrescoSpringTest * It checks that the ratings are applied correctly and that the cm:modifier is not * updated by these changes. */ - public void testApplyRating_MultipleUsers() throws Exception + @Test public void applyRating_MultipleUsers() throws Exception { - assertModifierIs(testDoc_Admin, AuthenticationUtil.getAdminUserName()); - - // 2 different users rating the same piece of content in the same rating scheme - AuthenticationUtil.setFullyAuthenticatedUser(USER_ONE); - ratingService.applyRating(testDoc_Admin, 4.0f, FIVE_STAR_SCHEME_NAME); - assertModifierIs(testDoc_Admin, AuthenticationUtil.getAdminUserName()); - - AuthenticationUtil.setFullyAuthenticatedUser(USER_TWO); - ratingService.applyRating(testDoc_Admin, 2.0f, FIVE_STAR_SCHEME_NAME); - assertModifierIs(testDoc_Admin, AuthenticationUtil.getAdminUserName()); - - float meanRating = ratingService.getAverageRating(testDoc_Admin, FIVE_STAR_SCHEME_NAME); - assertEquals("Document had wrong mean rating.", 3f, meanRating); - - float totalRating = ratingService.getTotalRating(testDoc_Admin, FIVE_STAR_SCHEME_NAME); - assertEquals("Document had wrong total rating.", 6.0f, totalRating); - - int ratingsCount = ratingService.getRatingsCount(testDoc_Admin, FIVE_STAR_SCHEME_NAME); - assertEquals("Document had wrong ratings count.", 2, ratingsCount); - - assertModifierIs(testDoc_Admin, AuthenticationUtil.getAdminUserName()); - - // One user removes their rating. - ratingService.removeRatingByCurrentUser(testDoc_Admin, FIVE_STAR_SCHEME_NAME); - - meanRating = ratingService.getAverageRating(testDoc_Admin, FIVE_STAR_SCHEME_NAME); - assertEquals("Document had wrong mean rating.", 4f, meanRating); - - totalRating = ratingService.getTotalRating(testDoc_Admin, FIVE_STAR_SCHEME_NAME); - assertEquals("Document had wrong total rating.", 4f, totalRating); - - ratingsCount = ratingService.getRatingsCount(testDoc_Admin, FIVE_STAR_SCHEME_NAME); - assertEquals("Document had wrong ratings count.", 1, ratingsCount); - - assertModifierIs(testDoc_Admin, AuthenticationUtil.getAdminUserName()); + TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback() + { + public Void execute() throws Throwable + { + assertModifierIs(testDoc_Admin, AuthenticationUtil.getAdminUserName()); + + // 2 different users rating the same piece of content in the same rating scheme + AuthenticationUtil.setFullyAuthenticatedUser(TEST_USER1.getUsername()); + RATING_SERVICE.applyRating(testDoc_Admin, 4.0f, FIVE_STAR_SCHEME_NAME); + assertModifierIs(testDoc_Admin, AuthenticationUtil.getAdminUserName()); + + AuthenticationUtil.setFullyAuthenticatedUser(TEST_USER2.getUsername()); + RATING_SERVICE.applyRating(testDoc_Admin, 2.0f, FIVE_STAR_SCHEME_NAME); + assertModifierIs(testDoc_Admin, AuthenticationUtil.getAdminUserName()); + + float meanRating = RATING_SERVICE.getAverageRating(testDoc_Admin, FIVE_STAR_SCHEME_NAME); + assertEquals("Document had wrong mean rating.", 3, (int)meanRating); + + float totalRating = RATING_SERVICE.getTotalRating(testDoc_Admin, FIVE_STAR_SCHEME_NAME); + assertEquals("Document had wrong total rating.", 6, (int)totalRating); + + int ratingsCount = RATING_SERVICE.getRatingsCount(testDoc_Admin, FIVE_STAR_SCHEME_NAME); + assertEquals("Document had wrong ratings count.", 2, ratingsCount); + + assertModifierIs(testDoc_Admin, AuthenticationUtil.getAdminUserName()); + + // One user removes their rating. + RATING_SERVICE.removeRatingByCurrentUser(testDoc_Admin, FIVE_STAR_SCHEME_NAME); + + meanRating = RATING_SERVICE.getAverageRating(testDoc_Admin, FIVE_STAR_SCHEME_NAME); + assertEquals("Document had wrong mean rating.", 4, (int)meanRating); + + totalRating = RATING_SERVICE.getTotalRating(testDoc_Admin, FIVE_STAR_SCHEME_NAME); + assertEquals("Document had wrong total rating.", 4, (int)totalRating); + + ratingsCount = RATING_SERVICE.getRatingsCount(testDoc_Admin, FIVE_STAR_SCHEME_NAME); + assertEquals("Document had wrong ratings count.", 1, ratingsCount); + + assertModifierIs(testDoc_Admin, AuthenticationUtil.getAdminUserName()); + + return null; + } + }); } /** @@ -353,62 +385,51 @@ public class RatingServiceIntegrationTest extends BaseAlfrescoSpringTest */ private void assertModifierIs(NodeRef nodeRef, final String expectedModifier) { - String actualModifier = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIER); + String actualModifier = (String)NODE_SERVICE.getProperty(nodeRef, ContentModel.PROP_MODIFIER); assertEquals("Incorrect cm:modifier", expectedModifier, actualModifier); } - public void testUsersCantRateTheirOwnContent() throws Exception + @Test public void usersCantRateTheirOwnContent() throws Exception { - // In the likes rating scheme, users can rate their own content. - AuthenticationUtil.setFullyAuthenticatedUser(USER_ONE); - ratingService.applyRating(testDoc_UserTwo, 1, LIKES_SCHEME_NAME); - - try + AuthenticationUtil.setFullyAuthenticatedUser(TEST_USER2.getUsername()); + + TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback() { - // But fiveStar rating scheme disallows rating your own content. - ratingService.applyRating(testDoc_UserTwo, 4, FIVE_STAR_SCHEME_NAME); - } - catch (RatingServiceException expected) - { - return; - } - fail("Expected exception not thrown"); + public Void execute() throws Throwable + { + // In the likes rating scheme, users can rate their own content. + RATING_SERVICE.applyRating(testDoc_UserTwo, 1, LIKES_SCHEME_NAME); + + // But fiveStar rating scheme disallows rating your own content. + boolean expectedExceptionThrown = false; + try + { + RATING_SERVICE.applyRating(testDoc_UserTwo, 4, FIVE_STAR_SCHEME_NAME); + } catch (RatingServiceException expected) + { + expectedExceptionThrown = true; + } + assertTrue(expectedExceptionThrown); + + return null; + } + }); } - private void createUser(String userName) + @Test public void javascriptAPI() throws Exception { - if (! authenticationService.authenticationExists(userName)) + TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback() { - authenticationService.createAuthentication(userName, "PWD".toCharArray()); - } - - if (! personService.personExists(userName)) - { - PropertyMap ppOne = new PropertyMap(4); - ppOne.put(ContentModel.PROP_USERNAME, userName); - ppOne.put(ContentModel.PROP_FIRSTNAME, "firstName"); - ppOne.put(ContentModel.PROP_LASTNAME, "lastName"); - ppOne.put(ContentModel.PROP_EMAIL, "email@email.com"); - ppOne.put(ContentModel.PROP_JOBTITLE, "jobTitle"); - - personService.createPerson(ppOne); - } - } - - private void deleteUser(String userName) - { - if (personService.personExists(userName)) - { - personService.deletePerson(userName); - } - } - - public void testJavascriptAPI() throws Exception - { - Map model = new HashMap(); - model.put("testNode", this.testDoc_UserOne); - - ScriptLocation location = new ClasspathScriptLocation("org/alfresco/repo/rating/script/test_ratingService.js"); - this.scriptService.executeScript(location, model); + public Void execute() throws Throwable + { + Map model = new HashMap(); + model.put("testNode", testDoc_UserOne); + + ScriptLocation location = new ClasspathScriptLocation("org/alfresco/repo/rating/script/test_ratingService.js"); + SCRIPT_SERVICE.executeScript(location, model); + + return null; + } + }); } } diff --git a/source/java/org/alfresco/util/test/junitrules/TemporaryNodes.java b/source/java/org/alfresco/util/test/junitrules/TemporaryNodes.java new file mode 100644 index 0000000000..162c0eb14d --- /dev/null +++ b/source/java/org/alfresco/util/test/junitrules/TemporaryNodes.java @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2005-2012 + Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.util.test.junitrules; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.rules.ExternalResource; + +/** + * A JUnit rule designed to help with the automatic cleanup of temporary test nodes. + * + * @author Neil Mc Erlean + * @since Odin + */ +public class TemporaryNodes extends ExternalResource +{ + private static final Log log = LogFactory.getLog(TemporaryNodes.class); + + private final ApplicationContextInit appContextRule; + private List temporaryNodeRefs = new ArrayList(); + + /** + * Constructs the rule with a reference to a {@link ApplicationContextInit rule} which can be used to retrieve the ApplicationContext. + * + * @param appContextRule a rule which can be used to retrieve the spring app context. + */ + public TemporaryNodes(ApplicationContextInit appContextRule) + { + this.appContextRule = appContextRule; + } + + + @Override protected void before() throws Throwable + { + // Intentionally empty + } + + @Override protected void after() + { + final RetryingTransactionHelper transactionHelper = (RetryingTransactionHelper) appContextRule.getApplicationContext().getBean("retryingTransactionHelper"); + final NodeService nodeService = (NodeService) appContextRule.getApplicationContext().getBean("nodeService"); + + // Run as admin to ensure all non-system nodes can be deleted irrespecive of which user created them. + AuthenticationUtil.runAs(new RunAsWork() + { + @Override public Void doWork() throws Exception + { + transactionHelper.doInTransaction(new RetryingTransactionCallback() + { + @Override public Void execute() throws Throwable + { + // Although we loop through all nodes, this is a cascade-delete and so we may only need to delete the first node. + for (NodeRef node : temporaryNodeRefs) + { + if (nodeService.exists(node)) + { + log.debug("Deleting temporary node " + nodeService.getProperty(node, ContentModel.PROP_NAME)); + nodeService.deleteNode(node); + } + } + + return null; + } + }); + return null; + } + }, AuthenticationUtil.getAdminUserName()); + } + + /** + * Add a specified NodeRef to the list of NodeRefs to be deleted by this rule. + * + * @param temporaryNodeRef a NodeRef + */ + public void addNodeRef(NodeRef temporaryNodeRef) + { + this.temporaryNodeRefs.add(temporaryNodeRef); + } + + /** + * This method creates a NodeRef and adds it to the internal list of NodeRefs to be tidied up by the rule. + * This method will be run in its own transaction and will be run with the specified user as the fully authenticated user, + * thus ensuring the named user is the cm:creator of the new node. + * + * @param parentNode the parent node + * @param nodeCmName the cm:name of the new node + * @param nodeType the type of the new node + * @param nodeCreator the username of the person who will create the node + * @return the newly created NodeRef. + */ + public NodeRef createNode(final NodeRef parentNode, final String nodeCmName, final QName nodeType, final String nodeCreator) + { + final RetryingTransactionHelper transactionHelper = (RetryingTransactionHelper) appContextRule.getApplicationContext().getBean("retryingTransactionHelper"); + + AuthenticationUtil.pushAuthentication(); + AuthenticationUtil.setFullyAuthenticatedUser(nodeCreator); + + NodeRef newNodeRef = transactionHelper.doInTransaction(new RetryingTransactionCallback() + { + public NodeRef execute() throws Throwable + { + final NodeService nodeService = (NodeService) appContextRule.getApplicationContext().getBean("nodeService"); + + Map props = new HashMap(); + props.put(ContentModel.PROP_NAME, nodeCmName); + QName childName = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, nodeCmName); + ChildAssociationRef childAssoc = nodeService.createNode(parentNode, + ContentModel.ASSOC_CONTAINS, + childName, + nodeType, + props); + return childAssoc.getChildRef(); + } + }); + + AuthenticationUtil.popAuthentication(); + + this.temporaryNodeRefs.add(newNodeRef); + return newNodeRef; + } +}