diff --git a/scm-test/src/main/java/sonia/scm/AbstractTestBase.java b/scm-test/src/main/java/sonia/scm/AbstractTestBase.java index d35ac129ee..2a8a43ad7a 100644 --- a/scm-test/src/main/java/sonia/scm/AbstractTestBase.java +++ b/scm-test/src/main/java/sonia/scm/AbstractTestBase.java @@ -35,7 +35,15 @@ package sonia.scm; //~--- non-JDK imports -------------------------------------------------------- +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.UnavailableSecurityManagerException; +import org.apache.shiro.subject.Subject; +import org.apache.shiro.subject.support.SubjectThreadState; +import org.apache.shiro.util.LifecycleUtils; +import org.apache.shiro.util.ThreadState; + import org.junit.After; +import org.junit.AfterClass; import org.junit.Before; import sonia.scm.util.IOUtil; @@ -56,6 +64,81 @@ import java.util.UUID; public class AbstractTestBase { + /** Field description */ + private static ThreadState subjectThreadState; + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + */ + @AfterClass + public static void tearDownShiro() + { + doClearSubject(); + + try + { + org.apache.shiro.mgt.SecurityManager securityManager = + getSecurityManager(); + + LifecycleUtils.destroy(securityManager); + } + catch (UnavailableSecurityManagerException e) + { + + // we don't care about this when cleaning up the test environment + // (for example, maybe the subclass is a unit test and it didn't + // need a SecurityManager instance because it was using only + // mock Subject instances) + } + + setSecurityManager(null); + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + protected static org.apache.shiro.mgt.SecurityManager getSecurityManager() + { + return SecurityUtils.getSecurityManager(); + } + + //~--- set methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param securityManager + */ + protected static void setSecurityManager( + org.apache.shiro.mgt.SecurityManager securityManager) + { + SecurityUtils.setSecurityManager(securityManager); + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + */ + private static void doClearSubject() + { + if (subjectThreadState != null) + { + subjectThreadState.clear(); + subjectThreadState = null; + } + } + /** * Method description * @@ -87,7 +170,7 @@ public class AbstractTestBase public void setUpTest() throws Exception { tempDirectory = new File(System.getProperty("java.io.tmpdir"), - UUID.randomUUID().toString()); + UUID.randomUUID().toString()); assertTrue(tempDirectory.mkdirs()); contextProvider = MockUtil.getSCMContextProvider(tempDirectory); postSetUp(); @@ -95,6 +178,27 @@ public class AbstractTestBase //~--- methods -------------------------------------------------------------- + /** + * Clears Shiro's thread state, ensuring the thread remains clean for future test execution. + */ + protected void clearSubject() + { + doClearSubject(); + } + + /** + * Method description + * + * + * @param subject + * + * @return + */ + protected ThreadState createThreadState(Subject subject) + { + return new SubjectThreadState(subject); + } + /** * Method description * @@ -111,6 +215,33 @@ public class AbstractTestBase */ protected void preTearDown() throws Exception {} + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + protected Subject getSubject() + { + return SecurityUtils.getSubject(); + } + + //~--- set methods ---------------------------------------------------------- + + /** + * Allows subclasses to set the currently executing {@link Subject} instance. + * + * @param subject the Subject instance + */ + protected void setSubject(Subject subject) + { + clearSubject(); + subjectThreadState = createThreadState(subject); + subjectThreadState.bind(); + } + ; //~--- fields --------------------------------------------------------------- diff --git a/scm-test/src/main/java/sonia/scm/util/MockUtil.java b/scm-test/src/main/java/sonia/scm/util/MockUtil.java index ba6d9c74f5..14a049e552 100644 --- a/scm-test/src/main/java/sonia/scm/util/MockUtil.java +++ b/scm-test/src/main/java/sonia/scm/util/MockUtil.java @@ -37,6 +37,12 @@ package sonia.scm.util; import com.google.inject.Provider; +import org.apache.shiro.authz.Permission; +import org.apache.shiro.subject.Subject; + +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + import sonia.scm.SCMContextProvider; import sonia.scm.user.User; import sonia.scm.web.security.DummyWebSecurityContext; @@ -48,6 +54,9 @@ import static org.mockito.Mockito.*; import java.io.File; +import java.util.Arrays; +import java.util.List; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -58,6 +67,45 @@ import javax.servlet.http.HttpServletResponse; public class MockUtil { + /** + * Method description + * + * + * @return + */ + public static Subject createAdminSubject() + { + Subject subject = mock(Subject.class); + + when(subject.isAuthenticated()).thenReturn(Boolean.TRUE); + when(subject.isPermitted(anyListOf(Permission.class))).then( + new Answer() + { + + @Override + public Boolean[] answer(InvocationOnMock invocation) throws Throwable + { + List permissions = + (List) invocation.getArguments()[0]; + Boolean[] returnArray = new Boolean[permissions.size()]; + + Arrays.fill(returnArray, Boolean.TRUE); + + return returnArray; + } + }); + when(subject.isPermitted(any(Permission.class))).thenReturn(Boolean.TRUE); + when(subject.isPermitted(any(String.class))).thenReturn(Boolean.TRUE); + when(subject.isPermittedAll(anyCollectionOf(Permission.class))).thenReturn( + Boolean.TRUE); + when(subject.isPermittedAll()).thenReturn(Boolean.TRUE); + when(subject.hasRole("admin")).thenReturn(Boolean.TRUE); + + return subject; + } + + //~--- get methods ---------------------------------------------------------- + /** * Method description * diff --git a/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java b/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java index 9ee0445345..72b8a768c8 100644 --- a/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java +++ b/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java @@ -37,11 +37,14 @@ package sonia.scm.repository; import com.google.inject.Provider; +import org.apache.shiro.subject.Subject; + +import org.junit.Before; import org.junit.Test; import sonia.scm.Type; -import sonia.scm.repository.xml.XmlRepositoryDAO; import sonia.scm.config.ScmConfiguration; +import sonia.scm.repository.xml.XmlRepositoryDAO; import sonia.scm.store.JAXBStoreFactory; import sonia.scm.store.StoreFactory; import sonia.scm.util.MockUtil; @@ -73,7 +76,7 @@ public class DefaultRepositoryManagerTest extends RepositoryManagerTestBase */ @Test public void getRepositoryFromRequestUriTest() - throws RepositoryException, IOException + throws RepositoryException, IOException { RepositoryManager m = createManager(); @@ -86,12 +89,26 @@ public class DefaultRepositoryManagerTest extends RepositoryManagerTestBase assertEquals("scm-test", m.getFromUri("hg/scm-test").getName()); assertEquals("scm-test", m.getFromUri("/hg/scm-test").getName()); assertEquals("project1/test-1", - m.getFromUri("/git/project1/test-1").getName()); + m.getFromUri("/git/project1/test-1").getName()); assertEquals("project1/test-1", - m.getFromUri("/git/project1/test-1/ka/some/path").getName()); + m.getFromUri("/git/project1/test-1/ka/some/path").getName()); assertNull(m.getFromUri("/git/project1/test-3/ka/some/path")); } + //~--- set methods ---------------------------------------------------------- + + /** + * Method description + * + */ + @Before + public void setAdminSubject() + { + Subject admin = MockUtil.createAdminSubject(); + + setSubject(admin); + } + //~--- methods -------------------------------------------------------------- /** @@ -138,8 +155,7 @@ public class DefaultRepositoryManagerTest extends RepositoryManagerTestBase ScmConfiguration configuration = new ScmConfiguration(); return new DefaultRepositoryManager(configuration, contextProvider, - MockUtil.getAdminSecurityContextProvider(), repositoryDAO, - handlerSet, listenerProvider, hookProvider); + repositoryDAO, handlerSet, listenerProvider, hookProvider); } /** @@ -153,7 +169,7 @@ public class DefaultRepositoryManagerTest extends RepositoryManagerTestBase * @throws RepositoryException */ private void createRepository(RepositoryManager m, Repository repository) - throws RepositoryException, IOException + throws RepositoryException, IOException { m.create(repository); }