JBoss Community

Writing a AS7 Test Case in testsuite module

modified by Brian Stansberry in JBoss AS7 Development - View the full document

Background

I wanted to write a test case for web security using FORM authentication in the AS7 testsuite. I chose the testsuite/integration submodule.

Requirements

 

  • I wanted to be able to run the test case in Eclipse.
  • I wanted to use JPDA to set breakpoints in the AS7 codebase.

 

Choices of Technologies

  • Arquilian
  • Shrinkwrap
  • JUnit
  • Eclipse

 

Note:  Both Arquilian and Shrinkwrap are available in the AS7 development environment by default.

 

Test Case

 

 

/*
 * JBoss, Home of Professional Open Source.
 * Copyright (c) 2011, Red Hat, Inc., and individual contributors
<snip> Copyright header
 */
package org.jboss.as.testsuite.integration.websecurity;
 
import static org.junit.Assert.assertEquals;
 
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
 
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.jboss.arquillian.api.Deployment;
import org.jboss.arquillian.api.Run;
import org.jboss.arquillian.api.RunModeType;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Test;
import org.junit.runner.RunWith;
 
/**
 * Unit Test web security
 * 
 * @author Anil Saldhana
 */
@RunWith(Arquillian.class)
@Run(RunModeType.AS_CLIENT)
public class WebSecurityFORMTestCase {
 
    private static final String URL = "http://localhost:8080/web-secure/secured/";
 
    @Deployment
    public static WebArchive deployment() {
        ClassLoader tccl = Thread.currentThread().getContextClassLoader();
        URL webxml = tccl.getResource("web-secure.war/web.xml");
        WebArchive war = ShrinkWrap.create(WebArchive.class, "web-secure.war");
        war.addClass(SecuredServlet.class);
 
        URL userProp = tccl.getResource("web-secure.war/users.properties");
        URL roleProp = tccl.getResource("web-secure.war/roles.properties");
        URL loginJSP = tccl.getResource("web-secure.war/login.jsp");
        URL errorJSP = tccl.getResource("web-secure.war/error.jsp");
 
        war.addResource(loginJSP, "login.jsp");
        war.addResource(errorJSP, "error.jsp");
 
        war.addResource(userProp, "/WEB-INF/classes/users.properties");
        war.addResource(roleProp, "/WEB-INF/classes/roles.properties");
 
        war.setWebXML(webxml);
 
        return war;
    }
 
    /**
     * Test with user "anil" who has the right password and the right role to access the servlet
     * 
     * @throws Exception
     */
    @Test
    public void testSuccessfulAuth() throws Exception {
        makeCall("anil", "anil", 200);
    }
 
    /**
     * <p>
     * Test with user "marcus" who has the right password but does not have the right role
     * </p>
     * <p>
     * Should be a HTTP/403
     * </p>
     * 
     * @throws Exception
     */
    @Test
    public void testUnsuccessfulAuth() throws Exception {
        makeCall("marcus", "marcus", 403);
    }
 
    protected void makeCall(String user, String pass, int expectedStatusCode) throws Exception {
        DefaultHttpClient httpclient = new DefaultHttpClient();
        try {
            HttpGet httpget = new HttpGet(URL);
 
            HttpResponse response = httpclient.execute(httpget);
 
            HttpEntity entity = response.getEntity();
            if (entity != null)
                entity.consumeContent();
 
            // We should get the Login Page
            StatusLine statusLine = response.getStatusLine();
            System.out.println("Login form get: " + statusLine);
            assertEquals(200, statusLine.getStatusCode());
 
            System.out.println("Initial set of cookies:");
            List<Cookie> cookies = httpclient.getCookieStore().getCookies();
            if (cookies.isEmpty()) {
                System.out.println("None");
            } else {
                for (int i = 0; i < cookies.size(); i++) {
                    System.out.println("- " + cookies.get(i).toString());
                }
            }
 
            // We should now login with the user name and password
            HttpPost httpost = new HttpPost(URL + "/j_security_check");
 
            List<NameValuePair> nvps = new ArrayList<NameValuePair>();
            nvps.add(new BasicNameValuePair("j_username", user));
            nvps.add(new BasicNameValuePair("j_password", pass));
 
            httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
 
            response = httpclient.execute(httpost);
            entity = response.getEntity();
            if (entity != null)
                entity.consumeContent();
 
            statusLine = response.getStatusLine();
 
            // Post authentication - we have a 302
            assertEquals(302, statusLine.getStatusCode());
            Header locationHeader = response.getFirstHeader("Location");
            String location = locationHeader.getValue();
 
            HttpGet httpGet = new HttpGet(location);
            response = httpclient.execute(httpGet);
 
            entity = response.getEntity();
            if (entity != null)
                entity.consumeContent();
 
            System.out.println("Post logon cookies:");
            cookies = httpclient.getCookieStore().getCookies();
            if (cookies.isEmpty()) {
                System.out.println("None");
            } else {
                for (int i = 0; i < cookies.size(); i++) {
                    System.out.println("- " + cookies.get(i).toString());
                }
            }
 
            // Either the authentication passed or failed based on the expected status code
            statusLine = response.getStatusLine();
            assertEquals(expectedStatusCode, statusLine.getStatusCode());
        } finally {
            // When HttpClient instance is no longer needed,
            // shut down the connection manager to ensure
            // immediate deallocation of all system resources
            httpclient.getConnectionManager().shutdown();
        }
    }
}

 

 

In this test case, I am specifying that the test case should run using Arquilian  (via @RunWith) annotation.  Plus I am telling Arquilian to run the test as a client test case and not inside AS7.  [via @Run(RunModeType.AS_CLIENT) ]  If you want the test to run inside AS7, then you have to use IN_CONTAINER (which is default anyway).

 

Also note above. that I am adding users.properties and roles.properties to WEB-INF/classes directory inside the Web Archive.

 

 

Web Deployment

I need the following Items in my web archive

  • Servlet
  • web.xml
  • Two properties files (users.properties and roles.properties)

 

 

Let us look at the servlet

 

 

/*
 * JBoss, Home of Professional Open Source.
 * Copyright (c) 2011, Red Hat, Inc., and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 * <SNIP>
 */
package org.jboss.as.testsuite.integration.websecurity;
 
import java.io.IOException;
import java.io.Writer;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.HttpConstraint;
import javax.servlet.annotation.ServletSecurity;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
/**
 * A simple servlet that just writes back a string
 * 
 * @author Anil Saldhana
 */
@WebServlet(urlPatterns = { "/secured/" })
@ServletSecurity(@HttpConstraint(rolesAllowed = { "gooduser" }))
public class SecuredServlet extends HttpServlet {
 
    private static final long serialVersionUID = 1L;
 
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 
        Writer writer = resp.getWriter();
        writer.write("GOOD");
    }
}

 

My test resources were in a folder as

 

 

web-secure.war/

login.jsp

error.jsp

users.properties

roles.properties

web.xml

 

Where should I look for the source code?


https://github.com/anilsaldhana/jboss-as/commit/0efdc673a45d6d172559183243a99e0927e33e65

 

Show me the test in action, buddy

 

 

anil@localhost:~/as7/jboss-as/testsuite/integration$ mvn clean install

Running org.jboss.as.testsuite.integration.websecurity.WebSecurityFORMTestCase
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.531 sec

 

Troubleshooting

 

  • How do I run AS7 with JPDA enabled?
    • Uncomment the following line in bin/standalone.conf
    • #JAVA_OPTS="$JAVA_OPTS -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y"
      
  • Any Eclipse settings for the test case?
    • VM arguments in the eclipse config for the test case was
    • -Djboss.home=/home/anil/as7/jboss-as/testsuite/integration/../../build/target/jboss-7.0.0.Beta2
      
  • How do I see what is in the web archive ShrinkWrap creates? You definitely need to add this always.
    • System.out.println(war.toString(true));
      
  • What about when Arquilian is running in a managed mode?
    • Stuart Douglas gave some insight into this.
    • There are two ways, you can either start a standalone instance and attach your 
      debugger to it normally,
      and then run
      
      mvn install -Premote  -Dtest=com.my.Test
      
      Alternatively 
      
      mvn install -Djboss.options="-Xdebug  -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8787"
      
      And then attach. This way will not let you use -Dtest= though,
       so generally when I am debugging I use the remote profile.
      

Comment by going to Community

Create a new document in JBoss AS7 Development at Community