/*
* JBoss, Home of Professional Open Source.
* Copyright 2011, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This 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 2.1 of
* the License, or (at your option) any later version.
*
* This software 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 this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.gatein.htmlunit.jira;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import org.jboss.gatein.htmlunit.AbstractWebTest;
import org.testng.Assert;
import org.testng.annotations.Test;
import org.testng.log4testng.Logger;
/**
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
*/
public class Test_GTNPORTAL_1823_FailToCreatePage extends AbstractWebTest {
/** Logger */
private static final Logger log = Logger.getLogger(Test_GTNPORTAL_1823_FailToCreatePage.class);
/** Number of concurrent threads for the test */
protected static final int TCOUNT = 2;
/** Counter for id generation */
protected static AtomicInteger idCounter = new AtomicInteger(1);
/** Down counter used to synchronize threads before clicking Finish */
protected static CountDownLatch sync = new CountDownLatch(TCOUNT);
/**
* Id for inclusion in page title so that every thread uses unique name for the newly added page
*
* @return id
*/
public String nextId() {
return "" + idCounter.getAndIncrement();
}
/**
* This test method relies on TestNG parallel test execution facility to perform two concurrent executions of this method on
* a single instance of the test class
*
* @throws Throwable if test fails
*/
@Test(invocationCount = TCOUNT, threadPoolSize = TCOUNT, groups = { "GateIn", "jira", "htmlunit" })
public void testMain() throws Throwable {
try {
test(false);
} finally {
// If exception occurs we don't want the other thread to lock up
// - so we perform another countDown()
sync.countDown();
}
}
/**
* Main body of the test
*
* @throws Throwable
*/
protected void test(boolean navNodeTest) throws Throwable {
String id = nextId();
String categoryTitle = "Gadgets";
String portletName = "Calculator";
String pageName = "TestPage" + id;
String portletElementToDnD = "//div[@id='" + categoryTitle + "/" + portletName + "']";
openPortal(true);
// Check that testPage with this name does not yet exist
Assert.assertFalse(isElementPresent("link=" + pageName), "Page exists already: " + pageName);
signInAsRoot();
// Add new page, but don't click Finish yet at the end
addNewPageUpToFinish(categoryTitle, portletName, pageName, portletElementToDnD);
// Wait for the other thread ...
sync.countDown();
sync.await();
if (navNodeTest && id.equals("2")) {
// Finish click concurrency is inappropriate for navNodeTest where we need predictable order
Thread.sleep(5000);
}
// Now click Finish (both threads at the same time)
finishPageEdit();
String failedText = "This node does not have any pages.";
String textPresent = waitForTextPresent(portletName, failedText);
Assert.assertNotSame(textPresent, failedText, "Concurrent Add Page issue reproduced!");
Assert.assertEquals(textPresent, portletName, "");
if (navNodeTest && id.equals("2")) {
// Check that both test pages' navigation nodes are present
Assert.assertTrue(isElementPresent("link=TestPage1"), "TestPage1 link presence");
Assert.assertTrue(isElementPresent("link=TestPage2"), "TestPage2 link presence");
}
finished();
}
/**
* Perform cleanup
*
* @throws IOException
*/
private void test2() throws IOException {
openPortal(true);
signInAsRoot();
cleanup();
}
/**
* TODO: Cleanup code doesn't yet work
*
* @throws IOException
*/
private void cleanup() {
try {
leavePageEdit();
} catch (Exception ex) {
log.warn("IGNORED: ", ex);
}
try {
goToPageManagement();
try {
searchAndDeletePage("TestPage1");
} catch (Throwable ex) {
log.warn("IGNORED: Failed to delete TestPage1: ", ex);
}
try {
searchAndDeletePage("TestPage2");
} catch (Throwable ex) {
log.warn("IGNORED: Failed to delete TestPage2: ", ex);
}
} catch (Throwable e) {
log.warn("IGNORED: Failed to open PageManagement: ", e);
}
try {
goToSiteManagement();
try {
editNavigation("classic");
deleteNode("TestPage");
} catch (Throwable ex) {
log.warn("IGNORED: Failed to delete TestPage1: ", ex);
}
try {
editNavigation("classic");
deleteNode("TestPage2");
} catch (Throwable ex) {
log.warn("IGNORED: Failed to delete TestPage2: ", ex);
}
} catch (Throwable e) {
log.warn("IGNORED: Failed to remove TestPage from navigation: ", e);
}
}
}