dev@javaserverfaces.java.net

[Review] Get unit tests running with Glassfish - Take 2

From: Ryan Lubke <Ryan.Lubke_at_Sun.COM>
Date: Wed, 14 Sep 2005 15:34:01 -0700

Use reflection in conjunction with suppressAccessChecks in server.policy
to allow unit tests that access private/package-private methods and members
to run in Glassfish.


SECTION: Modified Files
----------------------------
M build-tests.xml
  - changed javac source to 1.5
  - commented out RenderResponsePhaseTest since it
    relies on a bug on FacesContext.setViewRoot(). This
    test needs to be looked at

M build.xml
  - added config.appserver target which will update
    Glassfish's server.policy file:
      * update PropertyPermission to read and write
      * add the suppressAccessChecks option

M systest/build.xml
  - Include new TestingUtil class before compiling the rest
    of systest

M systest/src/com/sun/faces/application/ResetUniqueRequestIdBean.java
M test/com/sun/faces/application/TestApplicationImpl.java
M test/com/sun/faces/application/TestViewHandlerImpl.java
M test/com/sun/faces/config/StoreServletContext.java
M test/com/sun/faces/lifecycle/TestProcessEvents.java
M test/com/sun/faces/lifecycle/TestRestoreViewPhase.java
M test/com/sun/faces/lifecycle/TestSaveStateInPage.java
M test/com/sun/faces/taglib/jsf_core/TestViewTag.java
  - Leverage TestingUtil to access private/package-private
    members and methods

A test/com/sun/faces/util/TestingUtil.java
  - static convenience methods to wrap reflection machinery


SECTION: Diffs
----------------------------
Index: build-tests.xml
===================================================================
RCS file: /cvs/javaserverfaces-sources/jsf-ri/build-tests.xml,v
retrieving revision 1.221
diff -u -r1.221 build-tests.xml
--- build-tests.xml 22 Aug 2005 22:10:01 -0000 1.221
+++ build-tests.xml 14 Sep 2005 22:29:33 -0000
@@ -235,7 +235,7 @@
             destdir="${out.test.dir}/WEB-INF/classes"
             debug="${compile.debug}"
             optimize="${compile.optimize}"
- source="1.4"
+ source="1.5"
             deprecation="${compile.deprecation}">
 
             <classpath refid="compile.classpath"/>
@@ -373,8 +373,10 @@
             <test todir="${test.results.dir}"
name="com.sun.faces.lifecycle.TestPhase"/>
             <test todir="${test.results.dir}"
name="com.sun.faces.lifecycle.TestProcessEvents"/>
             <test todir="${test.results.dir}"
name="com.sun.faces.lifecycle.TestProcessValidationsPhase"/>
- <test todir="${test.results.dir}"
name="com.sun.faces.lifecycle.TestRenderResponsePhase"/>
- <test todir="${test.results.dir}"
name="com.sun.faces.lifecycle.TestRestoreViewPhase"/>
+ <test todir="${test.results.dir}"
name="com.sun.faces.lifecycle.TestRenderResponsePhase"/>
+ <!-- Commented out. This test relies heavily on a bug in
FacesContext.setViewRoot()
+ that allowed one to pass a null value in. This test
case needs to be revisited.
+ <test todir="${test.results.dir}"
name="com.sun.faces.lifecycle.TestRestoreViewPhase"/> -->
             <test todir="${test.results.dir}"
name="com.sun.faces.lifecycle.TestUpdateModelValuesPhase"/>
             <test todir="${test.results.dir}"
name="com.sun.faces.renderkit.html_basic.TestComponentType"/>
             <test todir="${test.results.dir}"
name="com.sun.faces.renderkit.html_basic.TestHtmlResponseWriter"/>
Index: build.xml
===================================================================
RCS file: /cvs/javaserverfaces-sources/jsf-ri/build.xml,v
retrieving revision 1.188
diff -u -r1.188 build.xml
--- build.xml 22 Aug 2005 22:10:01 -0000 1.188
+++ build.xml 14 Sep 2005 22:29:33 -0000
@@ -804,4 +804,18 @@
         <ant antfile="build-tests.xml" target="run.cactus.test.appserver"/>
     </target>
    
+ <target name="config.appserver">
+ <replace file="${tomcat.home}/domains/domain1/config/server.policy"
+ token="permission java.util.PropertyPermission
&quot;*&quot;, &quot;read&quot;;"
+ value="permission java.util.PropertyPermission
&quot;*&quot;, &quot;read,write&quot;;"/>
+ <concat append="true"
+
destfile="${tomcat.home}/domains/domain1/config/server.policy">
+grant {
+ permission java.lang.RuntimePermission
&quot;suppressAccessChecks&quot;;
+};
+ </concat>
+ <chmod file="${tomcat.home}/domains/domain1/config/server.policy"
+ perm="777"/>
+ </target>
+
 </project>
Index: systest/build.xml
===================================================================
RCS file: /cvs/javaserverfaces-sources/jsf-ri/systest/build.xml,v
retrieving revision 1.32
diff -u -r1.32 build.xml
--- systest/build.xml 22 Aug 2005 22:10:31 -0000 1.32
+++ systest/build.xml 14 Sep 2005 22:29:34 -0000
@@ -129,6 +129,7 @@
     <pathelement location="${jsp.jar}"/>
     <pathelement location="${jstl.jar}"/>
     <pathelement location="${junit.jar}"/>
+ <pathelement location="${build.home/WEB-INF/classes}"/>
     <fileset dir="${htmlunit.home}/lib" includes="*.jar"/>
   </path>
 
@@ -239,6 +240,14 @@
    description="Just compile the classes">
 
     <!-- Run javac through everything -->
+ <javac srcdir="${basedir}/../test"
+ destdir="${build.home}/WEB-INF/classes"
+ debug="${compile.debug}"
+ deprecation="${compile.deprecation}"
+ optimize="${compile.optimize}"
+ includes="**/TestingUtil**">
+ <classpath refid="compile.classpath"/>
+ </javac>
     <javac srcdir="${source.home}"
            destdir="${build.home}/WEB-INF/classes"
              debug="${compile.debug}"
Index: systest/src/com/sun/faces/application/ResetUniqueRequestIdBean.java
===================================================================
RCS file:
/cvs/javaserverfaces-sources/jsf-ri/systest/src/com/sun/faces/application/ResetUniqueRequestIdBean.java,v
retrieving revision 1.3
diff -u -r1.3 ResetUniqueRequestIdBean.java
---
systest/src/com/sun/faces/application/ResetUniqueRequestIdBean.java
22 Aug 2005 22:10:31 -0000 1.3
+++
systest/src/com/sun/faces/application/ResetUniqueRequestIdBean.java
14 Sep 2005 22:29:34 -0000
@@ -30,24 +30,34 @@
 package com.sun.faces.application;
 
 import javax.faces.context.FacesContext;
+
 import com.sun.faces.RIConstants;
+import com.sun.faces.util.TestingUtil;
+
 import org.apache.commons.collections.LRUMap;
 
-public class ResetUniqueRequestIdBean extends Object {
+public class ResetUniqueRequestIdBean {
 
- public ResetUniqueRequestIdBean() {}
+ public ResetUniqueRequestIdBean() {
+ }
 
     protected String reset = "Unique Id Counter Has Been Reset";
+
     public String getReset() {
- FacesContext context = FacesContext.getCurrentInstance();
- LRUMap lruMap = new LRUMap(15);
-
context.getExternalContext().getSessionMap().put(RIConstants.LOGICAL_VIEW_MAP,
lruMap);
-
((StateManagerImpl)context.getApplication().getStateManager()).requestIdSerial
= (char) -1;
- return reset;
+ FacesContext context = FacesContext.getCurrentInstance();
+ LRUMap lruMap = new LRUMap(15);
+
context.getExternalContext().getSessionMap().put(RIConstants.LOGICAL_VIEW_MAP,
lruMap);
+ StateManagerImpl stateManagerImpl =
+ (StateManagerImpl) context.getApplication().getStateManager();
+ TestingUtil.setPrivateField("requestIdSerial",
+ StateManagerImpl.class,
+ stateManagerImpl,
+ ((char) -1));
+ return reset;
     }
 
     public void setReset(String newReset) {
- reset = newReset;
+ reset = newReset;
     }
 
 }
Index: test/com/sun/faces/application/TestApplicationImpl.java
===================================================================
RCS file:
/cvs/javaserverfaces-sources/jsf-ri/test/com/sun/faces/application/TestApplicationImpl.java,v
retrieving revision 1.27
diff -u -r1.27 TestApplicationImpl.java
--- test/com/sun/faces/application/TestApplicationImpl.java 22 Aug
2005 22:11:09 -0000 1.27
+++ test/com/sun/faces/application/TestApplicationImpl.java 14 Sep
2005 22:29:34 -0000
@@ -33,9 +33,13 @@
 
 import com.sun.faces.JspFacesTestCase;
 import com.sun.faces.TestComponent;
+import com.sun.faces.RIConstants;
 import com.sun.faces.util.Util;
+import com.sun.faces.util.TestingUtil;
+
 import java.util.Locale;
 import java.util.ResourceBundle;
+import java.util.Map;
 
 import javax.faces.FacesException;
 import javax.faces.FactoryFinder;
@@ -576,10 +580,19 @@
     }
    
     public static void
clearResourceBundlesFromAssociate(ApplicationImpl application) {
- ApplicationAssociate associate = application.getAssociate();
+ ApplicationAssociate associate = (ApplicationAssociate)
+ TestingUtil.invokePrivateMethod("getAssociate",
+ RIConstants.EMPTY_CLASS_ARGS,
+ RIConstants.EMPTY_METH_ARGS,
+ ApplicationImpl.class,
+ application);
         if (null != associate) {
- if (null != associate.resourceBundles) {
- associate.resourceBundles.clear();
+ Map resourceBundles = (Map)
+ TestingUtil.getPrivateField("resourceBundles",
+ ApplicationAssociate.class,
+ associate);
+ if (null != resourceBundles) {
+ resourceBundles.clear();
             }
         }
     }
Index: test/com/sun/faces/application/TestViewHandlerImpl.java
===================================================================
RCS file:
/cvs/javaserverfaces-sources/jsf-ri/test/com/sun/faces/application/TestViewHandlerImpl.java,v
retrieving revision 1.27
diff -u -r1.27 TestViewHandlerImpl.java
--- test/com/sun/faces/application/TestViewHandlerImpl.java 22 Aug
2005 22:11:10 -0000 1.27
+++ test/com/sun/faces/application/TestViewHandlerImpl.java 14 Sep
2005 22:29:34 -0000
@@ -417,8 +417,7 @@
     public void testTransient() {
 
         // precreate tree and set it in session and make sure the tree is
- // restored from session.
- getFacesContext().setViewRoot(null);
+ // restored from session.
         UIViewRoot root =
Util.getViewHandler(getFacesContext()).createView(getFacesContext(), null);
         root.setViewId(TEST_URI);
 
Index: test/com/sun/faces/config/StoreServletContext.java
===================================================================
RCS file:
/cvs/javaserverfaces-sources/jsf-ri/test/com/sun/faces/config/StoreServletContext.java,v
retrieving revision 1.6
diff -u -r1.6 StoreServletContext.java
--- test/com/sun/faces/config/StoreServletContext.java 22 Aug 2005
22:11:12 -0000 1.6
+++ test/com/sun/faces/config/StoreServletContext.java 14 Sep 2005
22:29:34 -0000
@@ -38,6 +38,12 @@
 import java.util.Set;
 import java.util.Locale;
 import java.util.Iterator;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+
+import com.sun.faces.RIConstants;
+import com.sun.faces.util.TestingUtil;
+
 /**
  * <p>The purpose of this class is to call the package private
  * getThreadLocalServletContext() method to set the ServletContext into
@@ -46,30 +52,39 @@
 
 public class StoreServletContext extends Object {
     ExternalContext ec = null;
+
     public void setServletContext(ServletContext sc) {
         ec = new ServletContextAdapter(sc);
- ConfigureListener.getThreadLocalExternalContext().set(new
ServletContextAdapter(sc));
+
+ ThreadLocal<ServletContextAdapter> threadLocal =
+ (ThreadLocal<ServletContextAdapter>)
+
TestingUtil.invokePrivateMethod("getThreadLocalExternalContext",
+
RIConstants.EMPTY_CLASS_ARGS,
+
RIConstants.EMPTY_METH_ARGS,
+ ConfigureListener.class,
+ null);
+ threadLocal.set(new ServletContextAdapter(sc));
     }
-
+
     public ExternalContext getServletContextWrapper() {
         return ec;
     }
 
     public class ServletContextAdapter extends ExternalContext {
-
+
         private ServletContext servletContext = null;
         private ApplicationMap applicationMap = null;
-
+
         public ServletContextAdapter(ServletContext sc) {
             this.servletContext = sc;
         }
-
+
         public void dispatch(String path) throws java.io.IOException {
         }
-
+
         public String encodeActionURL(String url) {
             return null;
- }
+ }
 
         public String encodeNamespace(String name) {
             return null;
@@ -86,7 +101,7 @@
             }
             return applicationMap;
         }
-
+
         public String getAuthType() {
             return null;
         }
@@ -112,9 +127,9 @@
             return null;
         }
 
- public void setRequest(Object request) {}
-
-
+ public void setRequest(Object request) {}
+
+
         public String getRequestCharacterEncoding() {
             return null;
         }
@@ -128,7 +143,7 @@
         }
 
         public void setResponseCharacterEncoding(String
responseCharacterEncoding) {
- }
+ }
 
         public String getRequestContextPath() {
             return null;
@@ -186,18 +201,18 @@
         public String getRequestServletPath() {
             return null;
         }
-
-
+
+
         public String getRequestContentType() {
             return null;
         }
-
+
         public String getResponseContentType() {
             return null;
         }
 
- public java.net.URL getResource(String path) throws
- java.net.MalformedURLException {
+ public java.net.URL getResource(String path) throws
+
java.net.MalformedURLException {
             return null;
         }
 
@@ -214,7 +229,7 @@
             return null;
         }
 
- public void setResponse(Object response) {}
+ public void setResponse(Object response) {}
 
         public Object getSession(boolean create) {
             return null;
@@ -227,22 +242,22 @@
         public java.security.Principal getUserPrincipal() {
             return null;
         }
-
+
         public boolean isUserInRole(String role) {
             return false;
         }
 
         public void log(String message) {
         }
-
+
         public void log(String message, Throwable exception){
         }
-
+
         public void redirect(String url) throws java.io.IOException {
         }
 
     }
-
+
     class ApplicationMap extends java.util.AbstractMap {
 
         private ServletContext servletContext = null;
@@ -292,7 +307,7 @@
                 return false;
             return super.equals(obj);
         }
-
+
         public void clear() {
             throw new UnsupportedOperationException();
         }
@@ -300,7 +315,7 @@
         public void putAll(Map t) {
             throw new UnsupportedOperationException();
         }
-
+
 
     } // END ApplicationMap
 }
Index: test/com/sun/faces/lifecycle/TestProcessEvents.java
===================================================================
RCS file:
/cvs/javaserverfaces-sources/jsf-ri/test/com/sun/faces/lifecycle/TestProcessEvents.java,v
retrieving revision 1.19
diff -u -r1.19 TestProcessEvents.java
--- test/com/sun/faces/lifecycle/TestProcessEvents.java 22 Aug 2005
22:11:20 -0000 1.19
+++ test/com/sun/faces/lifecycle/TestProcessEvents.java 14 Sep 2005
22:29:34 -0000
@@ -110,8 +110,7 @@
     }
 
 
- public void tearDown() {
- getFacesContext().setViewRoot(null);
+ public void tearDown() {
         super.tearDown();
     }
 
Index: test/com/sun/faces/lifecycle/TestRestoreViewPhase.java
===================================================================
RCS file:
/cvs/javaserverfaces-sources/jsf-ri/test/com/sun/faces/lifecycle/TestRestoreViewPhase.java,v
retrieving revision 1.25
diff -u -r1.25 TestRestoreViewPhase.java
--- test/com/sun/faces/lifecycle/TestRestoreViewPhase.java 22 Aug
2005 22:11:21 -0000 1.25
+++ test/com/sun/faces/lifecycle/TestRestoreViewPhase.java 14 Sep
2005 22:29:34 -0000
@@ -136,7 +136,7 @@
     // here we do what the StateManager does to save the state in
     // the server.
     Util.getStateManager(context).saveSerializedView(context);
- context.setViewRoot(null);
+ //context.setViewRoot(null);
 
         Phase restoreView = new RestoreViewPhase();
 
@@ -162,7 +162,7 @@
         assertTrue(root.getChildCount() == 1);
         
assertTrue(basicForm.getId().equals(root.findComponent("basicForm").getId()));
     
assertTrue(userName.getId().equals(basicForm.findComponent("userName").getId()));
- getFacesContext().setViewRoot(null);
+ //getFacesContext().setViewRoot(null);
     }
 
     /**
@@ -199,7 +199,7 @@
     // here we do what the StateManager does to save the state in
     // the server.
     Util.getStateManager(context).saveSerializedView(context);
- context.setViewRoot(null);
+ //context.setViewRoot(null);
 
         Phase restoreView = new RestoreViewPhase();
 
@@ -216,7 +216,7 @@
         // Now test with no facets... Listeners should still be
registered on UICommand
         // components....
         //
- context.setViewRoot(null);
+ //context.setViewRoot(null);
 
         root = Util.getViewHandler(context).createView(context, null);
         root.setViewId(TEST_URI);
@@ -234,7 +234,7 @@
     // the server.
     
com.sun.faces.application.TestStateManagerImpl.resetStateManagerRequestIdSerialNumber(context);
     Util.getStateManager(context).saveSerializedView(context);
- context.setViewRoot(null);
+ //context.setViewRoot(null);
 
         restoreView = new RestoreViewPhase();
 
@@ -246,7 +246,7 @@
         assertTrue(!(context.getRenderResponse()) &&
                    !(context.getResponseComplete()));
 
- context.setViewRoot(null);
+ //context.setViewRoot(null);
     }
 
     public void beginRestoreViewExpired(WebRequest theRequest) {
@@ -280,7 +280,7 @@
         // here we do what the StateManager does to save the state in
         // the server.
         Util.getStateManager(context).saveSerializedView(context);
- context.setViewRoot(null);
+ //context.setViewRoot(null);
                                                                                                                         

         // invalidate the session before we attempt to restore
         
((HttpSession)context.getExternalContext().getSession(true)).invalidate();
Index: test/com/sun/faces/lifecycle/TestSaveStateInPage.java
===================================================================
RCS file:
/cvs/javaserverfaces-sources/jsf-ri/test/com/sun/faces/lifecycle/TestSaveStateInPage.java,v
retrieving revision 1.29
diff -u -r1.29 TestSaveStateInPage.java
--- test/com/sun/faces/lifecycle/TestSaveStateInPage.java 22 Aug 2005
22:11:21 -0000 1.29
+++ test/com/sun/faces/lifecycle/TestSaveStateInPage.java 14 Sep 2005
22:29:34 -0000
@@ -147,7 +147,7 @@
         // root is marked transient.
         // precreate tree and set it in session and make sure the tree is
         // restored from session.
- getFacesContext().setViewRoot(null);
+ //getFacesContext().setViewRoot(null);
         UIViewRoot root =
Util.getViewHandler(getFacesContext()).createView(getFacesContext(), null);
         root.setViewId(TEST_URI);
 
Index: test/com/sun/faces/taglib/jsf_core/TestViewTag.java
===================================================================
RCS file:
/cvs/javaserverfaces-sources/jsf-ri/test/com/sun/faces/taglib/jsf_core/TestViewTag.java,v
retrieving revision 1.12
diff -u -r1.12 TestViewTag.java
--- test/com/sun/faces/taglib/jsf_core/TestViewTag.java 22 Aug 2005
22:11:26 -0000 1.12
+++ test/com/sun/faces/taglib/jsf_core/TestViewTag.java 14 Sep 2005
22:29:34 -0000
@@ -35,6 +35,8 @@
 import com.sun.faces.lifecycle.Phase;
 import com.sun.faces.lifecycle.RenderResponsePhase;
 import com.sun.faces.util.Util;
+import com.sun.faces.util.TestingUtil;
+
 import org.apache.cactus.JspTestCase;
 import org.apache.cactus.WebRequest;
 
@@ -168,16 +170,39 @@
 
     public void testGetLocaleFromString() {
         ViewTag viewTag = new ViewTag();
- Locale locale = viewTag.getLocaleFromString("fr-FR");
+ Locale locale = (Locale)
+ TestingUtil.invokePrivateMethod("getLocaleFromString",
+ new Class[] { String.class },
+ new Object[] { "fr-FR" },
+ ViewTag.class,
+ viewTag);
         assertTrue(locale.equals(new Locale("fr", "FR")));
 
- locale = viewTag.getLocaleFromString("fr_FR");
+
+ locale = (Locale)
+ TestingUtil.invokePrivateMethod("getLocaleFromString",
+ new Class[] { String.class },
+ new Object[] { "fr_FR" },
+ ViewTag.class,
+ viewTag);
         assertTrue(locale.equals(new Locale("fr", "FR")));
 
- locale = viewTag.getLocaleFromString("fr");
+
+ locale = (Locale)
+ TestingUtil.invokePrivateMethod("getLocaleFromString",
+ new Class[] {String.class},
+ new Object[] {"fr"},
+ ViewTag.class,
+ viewTag);
         assertTrue(locale.equals(new Locale("fr", "")));
 
- locale = viewTag.getLocaleFromString("testLocale");
+
+ locale = (Locale)
+ TestingUtil.invokePrivateMethod("getLocaleFromString",
+ new Class[] {String.class},
+ new Object[] {"testLocale"},
+ ViewTag.class,
+ viewTag);
         assertTrue(locale.equals(Locale.getDefault()));
     }
 


SECTION: New Files
----------------------------
SEE ATTACHMENTS