SLING-3524: Added test case to verify login/logout/sudo functionality.
Added a parameterized test case to cover all possible combinations of
login, sudo and clone functionality. Removed the tests from
JcrResourceProviderTest that were made redundant by the new case.
diff --git a/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderSessionHandlingTest.java b/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderSessionHandlingTest.java
new file mode 100644
index 0000000..1fb61da
--- /dev/null
+++ b/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderSessionHandlingTest.java
@@ -0,0 +1,180 @@
+package org.apache.sling.jcr.resource.internal.helper.jcr;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.sameInstance;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeThat;
+import static org.junit.Assume.assumeTrue;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.Session;
+
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.commons.testing.jcr.RepositoryProvider;
+import org.apache.sling.jcr.api.SlingRepository;
+import org.apache.sling.jcr.resource.api.JcrResourceConstants;
+import org.apache.sling.spi.resource.provider.ResolveContext;
+import org.apache.sling.spi.resource.provider.ResourceProvider;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+import org.mockito.Mockito;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.component.ComponentContext;
+
+@RunWith(Parameterized.class)
+public class JcrResourceProviderSessionHandlingTest {
+
+ private enum LoginStyle {USER, SESSION};
+
+ private static final String AUTH_USER = "admin";
+ private static final char[] AUTH_PASSWORD = "admin".toCharArray();
+ private static final String SUDO_USER = "anonymous";
+
+ @Parameters(name = "loginStyle= {0}, sudo = {1}, clone = {2}")
+ public static List<Object[]> data() {
+
+ LoginStyle[] loginStyles = LoginStyle.values();
+ boolean[] sudoOptions = new boolean[] {false, true};
+ boolean[] cloneOptions = new boolean[] {false, true};
+
+ // Generate all possible combinations into data.
+ List<Object[]> data = new ArrayList<>();
+ Object[] dataPoint = new Object[3];
+ for (LoginStyle loginStyle : loginStyles) {
+ dataPoint[0] = loginStyle;
+ for (boolean sudo : sudoOptions) {
+ dataPoint[1] = sudo;
+ for (boolean clone : cloneOptions) {
+ dataPoint[2] = clone;
+ data.add(dataPoint.clone());
+ }
+ }
+ }
+ return data;
+ }
+
+ @Parameter(0)
+ public LoginStyle loginStyle;
+
+ @Parameter(1)
+ public boolean useSudo;
+
+ @Parameter(2)
+ public boolean doClone;
+
+ // Session we're using when loginStyle == SESSION, null otherwise.
+ private Session explicitSession;
+
+ private JcrResourceProvider jcrResourceProvider;
+ private JcrProviderState jcrProviderState;
+
+ @Before
+ public void setUp() throws Exception {
+ SlingRepository repo = RepositoryProvider.instance().getRepository();
+ Map<String, Object> authInfo = new HashMap<>();
+ switch (loginStyle) {
+ case USER:
+ authInfo.put(ResourceResolverFactory.USER, AUTH_USER);
+ authInfo.put(ResourceResolverFactory.PASSWORD, AUTH_PASSWORD);
+ break;
+ case SESSION:
+ explicitSession = repo.loginAdministrative(null);
+ authInfo.put(JcrResourceConstants.AUTHENTICATION_INFO_SESSION, explicitSession);
+ break;
+ }
+
+ if (useSudo) {
+ authInfo.put(ResourceResolverFactory.USER_IMPERSONATION, SUDO_USER);
+ }
+
+ if (doClone) {
+ authInfo.put(ResourceProvider.AUTH_CLONE, true);
+ }
+
+ ComponentContext ctx = mock(ComponentContext.class);
+ when(ctx.locateService(anyString(), Mockito.<ServiceReference<Object>>any())).thenReturn(repo);
+
+ jcrResourceProvider = new JcrResourceProvider();
+ jcrResourceProvider.activate(ctx);
+
+ jcrProviderState = jcrResourceProvider.authenticate(authInfo);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+
+ // Some tests do a logout, so check for liveness before trying to log out.
+ if (jcrProviderState.getSession().isLive()) {
+ jcrResourceProvider.logout(jcrProviderState);
+ }
+
+ jcrResourceProvider.deactivate();
+
+ if (explicitSession != null) {
+ explicitSession.logout();
+ }
+ }
+
+ @Test
+ public void sessionUsesCorrectUser() {
+ String expectedUser = useSudo ? SUDO_USER : AUTH_USER;
+ assertEquals(expectedUser, jcrProviderState.getSession().getUserID());
+ }
+
+ @Test
+ public void explicitSessionNotClosedOnLogout() {
+ assumeTrue(loginStyle == LoginStyle.SESSION);
+
+ jcrResourceProvider.logout(jcrProviderState);
+
+ assertTrue(explicitSession.isLive());
+ }
+
+ @Test
+ public void sessionsDoNotLeak() {
+ // This test is only valid if we either didn't pass an explicit session,
+ // or the provider had to clone it. Sessions created by the provider
+ // must be closed by the provider, or we have a session leak.
+ assumeThat(jcrProviderState.getSession(), is(not(sameInstance(explicitSession))));
+
+ jcrResourceProvider.logout(jcrProviderState);
+
+ assertFalse(jcrProviderState.getSession().isLive());
+ }
+
+ @Test
+ public void impersonatorIsReportedCorrectly() {
+ assumeTrue(useSudo);
+
+ @SuppressWarnings("unchecked")
+ ResolveContext<JcrProviderState> mockContext = mock(ResolveContext.class);
+ when(mockContext.getProviderState()).thenReturn(jcrProviderState);
+ Object reportedImpersonator = jcrResourceProvider.getAttribute(mockContext, ResourceResolver.USER_IMPERSONATOR);
+
+ assertEquals(AUTH_USER, reportedImpersonator);
+ }
+
+ @Test
+ public void clonesAreIndependent() {
+ assumeTrue(loginStyle == LoginStyle.SESSION && doClone);
+
+ assertNotSame(explicitSession, jcrProviderState.getSession());
+ }
+
+}
diff --git a/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderTest.java b/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderTest.java
index a520dc1..32c6bfb 100644
--- a/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderTest.java
+++ b/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderTest.java
@@ -19,20 +19,12 @@
package org.apache.sling.jcr.resource.internal.helper.jcr;
import java.security.Principal;
-import java.util.HashMap;
-import java.util.Map;
import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
import javax.jcr.Session;
-import javax.naming.NamingException;
-import org.apache.sling.api.resource.LoginException;
-import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.commons.testing.jcr.RepositoryTestBase;
-import org.apache.sling.jcr.resource.api.JcrResourceConstants;
import org.apache.sling.spi.resource.provider.ResolveContext;
-import org.apache.sling.spi.resource.provider.ResourceProvider;
import org.junit.Assert;
import org.mockito.Mockito;
import org.osgi.framework.ServiceReference;
@@ -66,25 +58,6 @@
Mockito.when(ctx.getProviderState()).thenReturn(new JcrProviderState(session, null, false));
Assert.assertNotNull(jcrResourceProvider.adaptTo(ctx, Principal.class));
}
-
- public void testLeakOnSudo() throws LoginException, RepositoryException, NamingException {
- Map<String, Object> authInfo = new HashMap<String, Object>();
- authInfo.put(JcrResourceConstants.AUTHENTICATION_INFO_SESSION, session);
- authInfo.put(ResourceResolverFactory.USER_IMPERSONATION, "anonymous");
- JcrProviderState providerState = jcrResourceProvider.authenticate(authInfo);
- Assert.assertNotEquals("Impersonation didn't start new session", session, providerState.getSession());
- jcrResourceProvider.logout(providerState);
- assertFalse("Impersonated session wasn't closed.", providerState.getSession().isLive());
- }
-
- public void testNoSessionSharing() throws LoginException {
- Map<String, Object> authInfo = new HashMap<String, Object>();
- authInfo.put(JcrResourceConstants.AUTHENTICATION_INFO_SESSION, session);
- authInfo.put(ResourceProvider.AUTH_CLONE, true);
- JcrProviderState providerState = jcrResourceProvider.authenticate(authInfo);
- Assert.assertNotEquals("Cloned resolver didn't clone session.", session, providerState.getSession());
- jcrResourceProvider.logout(providerState);
- }
}