diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/account/AccountManagement.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/account/AccountManagement.java index ba45448473..0de5299820 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/account/AccountManagement.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/account/AccountManagement.java @@ -18,8 +18,8 @@ package org.keycloak.testsuite.auth.page.account; import javax.ws.rs.core.UriBuilder; import org.jboss.arquillian.graphene.findby.FindByJQuery; -import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.testsuite.auth.page.AuthRealm; +import org.keycloak.testsuite.page.PageWithLogOutAction; import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; @@ -29,7 +29,7 @@ import org.openqa.selenium.support.FindBy; * @author Petr Mensik * @author tkyjovsk */ -public class AccountManagement extends AuthRealm { +public class AccountManagement extends AuthRealm implements PageWithLogOutAction { @Override public UriBuilder createUriBuilder() { @@ -76,7 +76,12 @@ public class AccountManagement extends AuthRealm { public void signOut() { signOutLink.click(); } - + + @Override + public void logOut() { + signOut(); + } + public void account() { accountLink.click(); } @@ -108,4 +113,5 @@ public class AccountManagement extends AuthRealm { public void waitForAccountLinkPresent() { waitUntilElement(accountLink, "account link should be present").is().present(); } + } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/AdminConsole.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/AdminConsole.java index 18a535281e..c46b59fb30 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/AdminConsole.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/AdminConsole.java @@ -25,6 +25,7 @@ import static org.keycloak.testsuite.auth.page.AuthRealm.MASTER; import org.keycloak.testsuite.auth.page.login.PageWithLoginUrl; import org.keycloak.testsuite.console.page.fragment.Menu; import org.keycloak.testsuite.console.page.fragment.ModalDialog; +import org.keycloak.testsuite.page.PageWithLogOutAction; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; @@ -32,8 +33,8 @@ import org.openqa.selenium.support.FindBy; * * @author Petr Mensik */ -public class AdminConsole extends AuthServer implements PageWithLoginUrl { - +public class AdminConsole extends AuthServer implements PageWithLoginUrl, PageWithLogOutAction { + public static final String ADMIN_REALM = "adminRealm"; public AdminConsole() { @@ -56,7 +57,7 @@ public class AdminConsole extends AuthServer implements PageWithLoginUrl { @Page private Menu menu; - + @FindBy(xpath = "//div[@class='modal-dialog']") protected ModalDialog modalDialog; @@ -79,7 +80,8 @@ public class AdminConsole extends AuthServer implements PageWithLoginUrl { @FindBy(css = "navbar-brand") protected WebElement brandLink; - + + @Override public void logOut() { menu.logOut(); } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/PageWithLogOutAction.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/PageWithLogOutAction.java new file mode 100644 index 0000000000..33fa4fcce7 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/PageWithLogOutAction.java @@ -0,0 +1,11 @@ +package org.keycloak.testsuite.page; + +/** + * + * @author tkyjovsk + */ +public interface PageWithLogOutAction { + + public void logOut(); + +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/SessionFailoverClusterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/SessionFailoverClusterTest.java index 3597b75e22..f15444d8f8 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/SessionFailoverClusterTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/SessionFailoverClusterTest.java @@ -1,17 +1,19 @@ package org.keycloak.testsuite.cluster; import java.util.List; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import org.junit.Ignore; import org.junit.Test; import org.keycloak.representations.idm.RealmRepresentation; import static org.keycloak.testsuite.auth.page.AuthRealm.ADMIN; -import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlDoesntStartWith; -import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith; import static org.keycloak.testsuite.util.WaitUtils.pause; import org.openqa.selenium.Cookie; +import org.keycloak.testsuite.page.AbstractPage; +import org.keycloak.testsuite.page.PageWithLogOutAction; +import org.junit.Before; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith; /** * @@ -20,77 +22,131 @@ import org.openqa.selenium.Cookie; public class SessionFailoverClusterTest extends AbstractClusterTest { public static final String KEYCLOAK_SESSION_COOKIE = "KEYCLOAK_SESSION"; - public static final String KEYCLOAK_IDENTITY_COOKIE = "KEYCLOAK_IDENTITY"; + + public static final Integer SESSION_CACHE_OWNERS = Integer.parseInt(System.getProperty("session.cache.owners", "1")); + public static final Integer OFFLINE_SESSION_CACHE_OWNERS = Integer.parseInt(System.getProperty("offline.session.cache.owners", "1")); + public static final Integer LOGIN_FAILURES_CACHE_OWNERS = Integer.parseInt(System.getProperty("login.failure.cache.owners", "1")); + + public static final Integer REBALANCE_WAIT = Integer.parseInt(System.getProperty("rebalance.wait", "5000")); @Override public void addTestRealms(List testRealms) { } - @Test - @Ignore("work in progress") // only works with owners="2" at the moment - public void sessionFailover() { - - // LOGIN - accountPage.navigateTo(); - driver.navigate().refresh(); - pause(3000); - loginPage.form().login(ADMIN, ADMIN); - assertCurrentUrlStartsWith(accountPage); - - Cookie sessionCookie = driver.manage().getCookieNamed(KEYCLOAK_SESSION_COOKIE); - assertNotNull(sessionCookie); - + @Before + public void beforeSessionFailover() { + log.info("Initial node failure"); failure(); + pause(REBALANCE_WAIT); + } - // check if session survived backend failure + @Test + public void sessionFailover() { + + boolean expectSuccessfulFailover = SESSION_CACHE_OWNERS >= getClusterSize(); + + log.info("SESSION FAILOVER TEST: cluster size = " + getClusterSize() + ", session-cache owners = " + SESSION_CACHE_OWNERS + + " --> Testsing for " + (expectSuccessfulFailover ? "" : "UN") + "SUCCESSFUL session failover."); + + assertEquals(2, getClusterSize()); - driver.navigate().refresh(); - pause(3000); - - assertCurrentUrlStartsWith(accountPage); - Cookie sessionCookieAfterFailover = driver.manage().getCookieNamed(KEYCLOAK_SESSION_COOKIE); - assertNotNull(sessionCookieAfterFailover); - assertEquals(sessionCookieAfterFailover.getValue(), sessionCookie.getValue()); + sessionFailover(expectSuccessfulFailover); + } - failback(); - iterateCurrentFailNode(); + protected void sessionFailover(boolean expectSuccessfulFailover) { - // check if session survived backend failback - driver.navigate().refresh(); - pause(3000); - assertCurrentUrlStartsWith(accountPage); - Cookie sessionCookieAfterFailback = driver.manage().getCookieNamed(KEYCLOAK_SESSION_COOKIE); - assertNotNull(sessionCookieAfterFailback); - assertEquals(sessionCookieAfterFailover.getValue(), sessionCookie.getValue()); + // LOGIN + Cookie sessionCookie = login(accountPage); + + switchFailedNode(); + + // VERIFY + if (expectSuccessfulFailover) { + verifyLoggedIn(accountPage, sessionCookie); + } else { + verifyLoggedOut(accountPage); + // FIXME test fails if I put re-login here + } + + switchFailedNode(); + + // VERIFY again + if (expectSuccessfulFailover) { + verifyLoggedIn(accountPage, sessionCookie); + } else { + verifyLoggedOut(accountPage); + login(accountPage); + } // LOGOUT - accountPage.navigateTo(); - accountPage.signOut(); + logout(accountPage); + verifyLoggedOut(accountPage); - assertCurrentUrlDoesntStartWith(accountPage); - masterRealmPage.navigateTo(); - sessionCookie = driver.manage().getCookieNamed(KEYCLOAK_SESSION_COOKIE); - assertNull(sessionCookie); + switchFailedNode(); - failure(); - - // check if session survived backend failure - driver.navigate().refresh(); - pause(3000); - assertCurrentUrlDoesntStartWith(accountPage); - masterRealmPage.navigateTo(); - sessionCookieAfterFailover = driver.manage().getCookieNamed(KEYCLOAK_SESSION_COOKIE); - assertNull(sessionCookieAfterFailover); + // VERIFY + verifyLoggedOut(accountPage); + + } + + /** + * failure --> failback --> failure of next node + */ + protected void switchFailedNode() { + assertFalse(controller.isStarted(getCurrentFailNode().getQualifier())); failback(); - - // check if session survived backend failback - driver.navigate().refresh(); - pause(3000); - assertCurrentUrlDoesntStartWith(accountPage); + pause(REBALANCE_WAIT); + + iterateCurrentFailNode(); + + failure(); + pause(REBALANCE_WAIT); + + assertFalse(controller.isStarted(getCurrentFailNode().getQualifier())); + } + + protected Cookie login(AbstractPage targetPage) { + targetPage.navigateTo(); + assertCurrentUrlStartsWith(loginPage); + loginPage.form().login(ADMIN, ADMIN); + assertCurrentUrlStartsWith(targetPage); + Cookie sessionCookie = driver.manage().getCookieNamed(KEYCLOAK_SESSION_COOKIE); + assertNotNull(sessionCookie); + return sessionCookie; + } + + protected void logout(AbstractPage targetPage) { + if (!(targetPage instanceof PageWithLogOutAction)) { + throw new IllegalArgumentException(targetPage.getClass().getSimpleName() + " must implement PageWithLogOutAction interface"); + } + targetPage.navigateTo(); + assertCurrentUrlStartsWith(targetPage); + ((PageWithLogOutAction) targetPage).logOut(); + } + + protected Cookie verifyLoggedIn(AbstractPage targetPage, Cookie sessionCookieForVerification) { + // verify on realm path masterRealmPage.navigateTo(); - sessionCookieAfterFailback = driver.manage().getCookieNamed(KEYCLOAK_SESSION_COOKIE); - assertNull(sessionCookieAfterFailback); + Cookie sessionCookieOnRealmPath = driver.manage().getCookieNamed(KEYCLOAK_SESSION_COOKIE); + assertNotNull(sessionCookieOnRealmPath); + assertEquals(sessionCookieOnRealmPath.getValue(), sessionCookieForVerification.getValue()); + // verify on target page + targetPage.navigateTo(); + assertCurrentUrlStartsWith(targetPage); + Cookie sessionCookie = driver.manage().getCookieNamed(KEYCLOAK_SESSION_COOKIE); + assertNotNull(sessionCookie); + assertEquals(sessionCookie.getValue(), sessionCookieForVerification.getValue()); + return sessionCookie; + } + + protected void verifyLoggedOut(AbstractPage targetPage) { + // verify on target page + targetPage.navigateTo(); + driver.navigate().refresh(); + assertCurrentUrlStartsWith(loginPage); + Cookie sessionCookie = driver.manage().getCookieNamed(KEYCLOAK_SESSION_COOKIE); + assertNull(sessionCookie); } }