You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2010/07/14 00:57:42 UTC

svn commit: r963899 [6/7] - in /myfaces/tomahawk/trunk/core20: ./ src/test/java/org/apache/myfaces/component/ src/test/java/org/apache/myfaces/component/html/ src/test/java/org/apache/myfaces/component/html/ext/ src/test/java/org/apache/myfaces/convert...

Added: myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/renderkit/html/util/AddResourceTest.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/renderkit/html/util/AddResourceTest.java?rev=963899&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/renderkit/html/util/AddResourceTest.java (added)
+++ myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/renderkit/html/util/AddResourceTest.java Tue Jul 13 22:57:38 2010
@@ -0,0 +1,362 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.renderkit.html.util;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.myfaces.test.AbstractTomahawkViewControllerTestCase;
+import org.apache.myfaces.test.mock.MockExternalContext;
+import org.apache.myfaces.test.mock.MockPrintWriter;
+import org.apache.myfaces.test.mock.MockResponseWriter;
+import org.apache.myfaces.webapp.filter.servlet.AbstractAttributeMap;
+
+/**
+ * Unit test for the AddResource class which can output script, style and inline
+ * javascript into the header or body of an HTML response page.
+ */
+public class AddResourceTest extends AbstractTomahawkViewControllerTestCase
+{
+    public AddResourceTest(String name)
+    {
+        super(name);
+    }
+
+    public void testGetInstance()
+    {
+
+       Map cacheMap = new LinkedHashMap();
+
+        AddResource instance1 = AddResourceFactory.getInstance(null,cacheMap, "/test1", null);
+        assertNotNull(instance1);
+
+        /* no longer true
+        AddResource instance2 = AddResourceFactory.getInstance(null, "/test2", null);
+        assertNotSame(instance1, instance2);
+        */
+
+        AddResourceFactory.getInstance(null,cacheMap, "/test1", null);
+    }
+    
+    /*
+    public void setUp()
+    {
+        // Make sure a FacesContext configured from some previous test case
+        // doesn't interfere with the test case we are about to run...
+        FacesContextHelper.setCurrentInstance(null);
+    }
+
+    public void tearDown()
+    {
+        // Make sure a FacesContext we may have configured in the test case
+        // just completed doesn't interfere with test cases run later.
+        FacesContextHelper.setCurrentInstance(null);
+    }
+    */
+
+    /**
+     * Simple test helper class to allow unit tests to configure
+     * mock FacesContext objects as the "current instance".
+     * <p>
+     * The method FacesContext.setCurrentInstance is protected, and
+     * hence cannot be accessed by unit tests wanting to configure
+     * a mock object as the value seen by code calling method
+     * FacesContext.getCurrentInstance().
+     */
+    /*
+    private static abstract class FacesContextHelper extends FacesContext
+    {
+        public static void setCurrentInstance(FacesContext other)
+        {
+            FacesContext.setCurrentInstance(other);
+        }
+    }*/
+
+    /**
+     * Configure a fake JSF environment for a test, consisting of a
+     * FacesContext and dependent objects.
+     * <p>
+     * EasyMock control objects are used to emulate the necessary bits.
+     */
+    /*
+    private static class MockState
+    {
+        Writer _writer;
+        ResponseWriter _htmlResponseWriter;
+        MockControl _servletRequestControl;
+        HttpServletRequest _servletRequest;
+        MockControl _servletResponseControl;
+        HttpServletResponse _servletResponse;
+        FacesContext _facesContext;
+
+        public void setup() throws IOException
+        {
+            // set up a writer object to be the "response" output stream.
+            _writer = new StringWriter();
+            String contentType = "text/html";
+            String charEncoding = "UTF-8";
+            _htmlResponseWriter = new HtmlResponseWriterImpl(_writer, contentType, charEncoding);
+
+            // Mock ServletRequest object that:
+            // * returns "/test" for context path
+            // * returns "/test/foo.jsp" for servlet path
+            // * returns "null" for getPathInfo
+            // * returns "null" for getHeader
+            // * returns "null" for getAttribute
+            // * returns null for getSession
+            _servletRequestControl = MockControl.createControl(HttpServletRequest.class);
+            _servletRequest = (HttpServletRequest) _servletRequestControl.getMock();
+            _servletRequest.getContextPath();
+            _servletRequestControl.setReturnValue("/test", MockControl.ZERO_OR_MORE);
+            _servletRequest.getServletPath();
+            _servletRequestControl.setReturnValue("/test/foo.jsp", MockControl.ZERO_OR_MORE);
+            _servletRequest.getPathInfo();
+            _servletRequestControl.setReturnValue("", MockControl.ZERO_OR_MORE);
+            _servletRequest.getHeader("");
+            _servletRequestControl.setMatcher(MockControl.ALWAYS_MATCHER);
+            _servletRequestControl.setReturnValue(null, MockControl.ZERO_OR_MORE);
+            _servletRequest.getAttribute("");
+            _servletRequestControl.setMatcher(MockControl.ALWAYS_MATCHER);
+            _servletRequestControl.setReturnValue(null, MockControl.ZERO_OR_MORE);
+            _servletRequest.setAttribute("", "");
+            _servletRequestControl.setMatcher(MockControl.ALWAYS_MATCHER);
+            _servletRequestControl.setVoidCallable(MockControl.ZERO_OR_MORE);
+            _servletRequest.getSession(false);
+            _servletRequestControl.setReturnValue(null, MockControl.ZERO_OR_MORE);
+            _servletRequestControl.replay();
+
+            // Mock ServletResponse object that:
+            // * returns appropriate encoded URLs
+            // * returns a PrintWriter wrapping this object's writer member for
+            //   calls to getWriter
+            _servletResponseControl = MockControl.createControl(HttpServletResponse.class);
+            _servletResponse = (HttpServletResponse) _servletResponseControl.getMock();
+            _servletResponse.encodeURL("/test/scripts/script1");
+            _servletResponseControl.setReturnValue("encoded(/test/scripts/script1)", MockControl.ZERO_OR_MORE);
+            _servletResponse.getWriter();
+            _servletResponseControl.setReturnValue(new PrintWriter(_writer), MockControl.ZERO_OR_MORE);
+            _servletResponse.getCharacterEncoding();
+            _servletResponseControl.setReturnValue("UTF-8", MockControl.ZERO_OR_MORE);
+            _servletResponseControl.replay();
+
+            // The FacesContext needs FactoryFinder configured.
+            FactoryFinder.setFactory(FactoryFinder.APPLICATION_FACTORY, ApplicationFactoryImpl.class.getName());
+            FactoryFinder.setFactory(FactoryFinder.RENDER_KIT_FACTORY, RenderKitFactoryImpl.class.getName());
+
+            // Now create a FacesContext....
+            _facesContext = new ServletFacesContextImpl(null,
+                    _servletRequest, _servletResponse);
+            _facesContext.setResponseWriter(_htmlResponseWriter);
+        }
+
+        public void verifyControls()
+        {
+            _servletRequestControl.verify();
+            _servletResponseControl.verify();
+        }
+    }*/
+
+    public void testAddJavaScriptHere() throws IOException
+    {
+        //MockState mockState = new MockState();
+        //mockState.setup();
+
+        request.setPathElements("/test", "", "", "");
+        // now start the test
+        AddResource instance1 = AddResourceFactory.getInstance(null,null,"/test", null);
+        instance1.addJavaScriptHere(facesContext, "/scripts/script1");
+
+        // verify that our mock objects got the expected callbacks
+        //mockState.verifyControls();
+
+        // verify that:
+        // *script tag is output
+        // * type attribute is right,
+        // * URL has context path prepended to it
+        // * URL has been encoded
+        // * HTML comments have been used to hide script from non-script-aware
+        //   browsers.
+        //
+        // NOTE: are comments required to hide this script from browsers when
+        // there isn't any script body content (just a src attr)?
+        String scriptValue = ((MockResponseWriter)facesContext.getResponseWriter()).getWriter().toString(); 
+        
+        assertEquals(scriptValue, "<script type=\"text/javascript\" src=\"/test/scripts/script1\"/>");
+    }
+    
+    public static class CustomMockExternalContext extends MockExternalContext
+    {
+        private Map _requestHeaderMap;
+        private Map _requestHeaderValuesMap;
+        
+        public CustomMockExternalContext(ServletContext context,
+                HttpServletRequest request, HttpServletResponse response)
+        {
+            super(context, request, response);
+        }
+
+        @Override
+        public Map getRequestHeaderMap()
+        {
+            if (_requestHeaderMap == null)
+            {
+                _requestHeaderMap = new RequestHeaderMap((HttpServletRequest)request);
+            }
+            return _requestHeaderMap;                        
+        }
+
+        @Override
+        public Map getRequestHeaderValuesMap()
+        {
+            if (_requestHeaderValuesMap == null)
+            {
+                _requestHeaderValuesMap = new RequestHeaderValuesMap((HttpServletRequest)request);
+            }
+            return _requestHeaderValuesMap;
+        }
+    }
+    
+    public static class RequestHeaderMap extends AbstractAttributeMap
+    {
+        private final HttpServletRequest _httpServletRequest;
+
+        RequestHeaderMap(HttpServletRequest httpServletRequest)
+        {
+            _httpServletRequest = httpServletRequest;
+        }
+
+        protected Object getAttribute(String key)
+        {
+            return _httpServletRequest.getHeader(key);
+        }
+
+        protected void setAttribute(String key, Object value)
+        {
+            throw new UnsupportedOperationException(
+                "Cannot set HttpServletRequest Header");
+        }
+
+        protected void removeAttribute(String key)
+        {
+            throw new UnsupportedOperationException(
+                "Cannot remove HttpServletRequest Header");
+        }
+
+        protected Enumeration getAttributeNames()
+        {
+            return _httpServletRequest.getHeaderNames();
+        }
+
+        public void putAll(Map t)
+        {
+            throw new UnsupportedOperationException();
+        }
+
+
+        public void clear()
+        {
+            throw new UnsupportedOperationException();
+        }    
+    }
+
+    public static class RequestHeaderValuesMap extends AbstractAttributeMap
+    {
+        private final HttpServletRequest _httpServletRequest;
+        private final Map                _valueCache = new HashMap();
+
+        RequestHeaderValuesMap(HttpServletRequest httpServletRequest)
+        {
+            _httpServletRequest = httpServletRequest;
+        }
+
+        protected Object getAttribute(String key)
+        {
+            Object ret = _valueCache.get(key);
+            if (ret == null)
+            {
+                _valueCache.put(key, ret = toArray(_httpServletRequest
+                    .getHeaders(key)));
+            }
+
+            return ret;
+        }
+
+        protected void setAttribute(String key, Object value)
+        {
+            throw new UnsupportedOperationException(
+                "Cannot set HttpServletRequest HeaderValues");
+        }
+
+        protected void removeAttribute(String key)
+        {
+            throw new UnsupportedOperationException(
+                "Cannot remove HttpServletRequest HeaderValues");
+        }
+
+        protected Enumeration getAttributeNames()
+        {
+            return _httpServletRequest.getHeaderNames();
+        }
+
+        private String[] toArray(Enumeration e)
+        {
+            List ret = new ArrayList();
+
+            while (e.hasMoreElements())
+            {
+                ret.add(e.nextElement());
+            }
+
+            return (String[]) ret.toArray(new String[ret.size()]);
+        }
+    }
+
+    public void testWriteWithFullHeader() throws IOException
+    {
+        //MockState mockState = new MockState();
+        //mockState.setup();
+        externalContext = new CustomMockExternalContext(servletContext, request, response);
+        facesContext.setExternalContext(externalContext);
+
+        request.setPathElements("/test", "", "", "");
+        String originalResponse =
+            "<html><head></head><body></body></html>";
+
+        AddResource ar = AddResourceFactory.getInstance(null,null,"/test", null);
+        ar.parseResponse(request,originalResponse,response);
+        ar.writeWithFullHeader(request,response);
+        ar.writeResponse(request,response);
+
+        //mockState.verifyControls();
+
+        String returnedResponse = new String(((MockPrintWriter)response.getWriter()).content());
+        
+        //System.out.println(facesContext.getResponseWriter().toString());
+        assertEquals(originalResponse, returnedResponse);
+    }
+}

Added: myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/renderkit/html/util/ReducedHTMLParserTest.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/renderkit/html/util/ReducedHTMLParserTest.java?rev=963899&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/renderkit/html/util/ReducedHTMLParserTest.java (added)
+++ myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/renderkit/html/util/ReducedHTMLParserTest.java Tue Jul 13 22:57:38 2010
@@ -0,0 +1,511 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.renderkit.html.util;
+
+import junit.framework.TestCase;
+import org.apache.myfaces.renderkit.html.util.CallbackListener;
+import org.apache.myfaces.renderkit.html.util.ReducedHTMLParser;
+
+/**
+ * Unit test for the ReducedHTMLParser class which detects tags within an HTML document.
+ */
+public class ReducedHTMLParserTest extends TestCase
+{
+    public static class ParseCallbackListener implements CallbackListener
+    {
+        int beforeHeadStart = -1;
+        int afterHeadStart = -1;
+        int beforeHeadEnd = -1;
+        int afterHeadEnd = -1;
+        int beforeBodyStart = -1;
+        int afterBodyStart = -1;
+        int beforeBodyEnd = -1;
+        int afterBodyEnd = -1;
+
+        public void openedStartTag(int charIndex, int tagIdentifier)
+        {
+            if (tagIdentifier == ReducedHTMLParser.HEAD_TAG)
+            {
+                beforeHeadStart = charIndex;
+            }
+            else if (tagIdentifier == ReducedHTMLParser.BODY_TAG)
+            {
+                beforeBodyStart = charIndex;
+            }
+        }
+
+        public void closedStartTag(int charIndex, int tagIdentifier)
+        {
+            if (tagIdentifier == ReducedHTMLParser.HEAD_TAG)
+            {
+                afterHeadStart = charIndex;
+            }
+            else if (tagIdentifier == ReducedHTMLParser.BODY_TAG)
+            {
+                afterBodyStart = charIndex;
+            }
+        }
+
+        public void openedEndTag(int charIndex, int tagIdentifier)
+        {
+            if (tagIdentifier == ReducedHTMLParser.HEAD_TAG)
+            {
+                beforeHeadEnd = charIndex;
+            }
+            else if (tagIdentifier == ReducedHTMLParser.BODY_TAG)
+            {
+                beforeBodyEnd = charIndex;
+            }
+        }
+
+        public void closedEndTag(int charIndex, int tagIdentifier)
+        {
+            if (tagIdentifier == ReducedHTMLParser.HEAD_TAG)
+            {
+                afterHeadEnd = charIndex;
+            }
+            else if (tagIdentifier == ReducedHTMLParser.BODY_TAG)
+            {
+                afterBodyEnd = charIndex;
+            }
+        }
+
+        public void attribute(int charIndex, int tagIdentifier, String key, String value)
+        {
+        }
+    }
+
+    public void testIsFinished1()
+    {
+        CharSequence seq = "";
+        CallbackListener listener = new ParseCallbackListener();
+        ReducedHTMLParser parser = new ReducedHTMLParser(seq, listener);
+        assertTrue("Empty sequence is finished", parser.isFinished());
+    }
+
+    public void testIsFinished2()
+    {
+        CharSequence seq = "xx yy";
+        CallbackListener listener = new ParseCallbackListener();
+        ReducedHTMLParser parser = new ReducedHTMLParser(seq, listener);
+
+        assertFalse("Sequence is finished", parser.isFinished());
+        parser.consumeNonWhitespace();
+        assertFalse("Sequence is finished", parser.isFinished());
+        parser.consumeWhitespace();
+        assertFalse("Sequence is finished", parser.isFinished());
+        parser.consumeNonWhitespace();
+        assertTrue("Sequence is finished", parser.isFinished());
+    }
+
+    public void testConsumeWhitespace()
+    {
+        CharSequence seq = "  \t  \r\n   xx    yy  ";
+        CallbackListener listener = new ParseCallbackListener();
+        ReducedHTMLParser parser = new ReducedHTMLParser(seq, listener);
+
+        // test that one call consumes all available whitespace
+        // and that all sorts of whitespace are consumed.
+        assertFalse("Sequence is finished", parser.isFinished());
+        parser.consumeWhitespace();
+        String word1 = parser.consumeNonWhitespace();
+        assertEquals("xx found", "xx", word1);
+
+        // test that multiple calls don't consume anything but whitespace
+        parser.consumeWhitespace();
+        parser.consumeWhitespace();
+        parser.consumeWhitespace();
+        String word2 = parser.consumeNonWhitespace();
+        assertEquals("yy found", "yy", word2);
+
+        // test that no failure occurs from consuming whitespace at the
+        // end of the sequence
+        assertFalse("Sequence is finished", parser.isFinished());
+        parser.consumeWhitespace();
+        parser.consumeWhitespace();
+        assertTrue("Sequence is finished", parser.isFinished());
+    }
+
+    public void testConsumeNonWhitespace()
+    {
+        CharSequence seq = "xx yy zz";
+        CallbackListener listener = new ParseCallbackListener();
+        ReducedHTMLParser parser = new ReducedHTMLParser(seq, listener);
+
+        String word1 = parser.consumeNonWhitespace();
+        assertEquals("xx found", "xx", word1);
+
+        // test that a call against whitespace returns null
+        String noWord = parser.consumeNonWhitespace();
+        assertNull("ConsumeNonWhitespace when whitespace is present", noWord);
+
+        // test that no exception is generated for multiple calls
+        parser.consumeNonWhitespace();
+        parser.consumeNonWhitespace();
+
+        parser.consumeWhitespace();
+        String word2 = parser.consumeNonWhitespace();
+        assertEquals("yy found", "yy", word2);
+
+        // test word that is at end of sequence
+        parser.consumeWhitespace();
+        String word3 = parser.consumeNonWhitespace();
+        assertEquals("zz found", "zz", word3);
+
+        // test that isFinished is set
+        assertTrue("Sequence is finished", parser.isFinished());
+
+        // test that no failure occurs from consuming nonwhitespace at the
+        // end of the sequence
+        noWord = parser.consumeNonWhitespace();
+        assertNull("ConsumeNonWhitespace at end of sequence", noWord);
+    }
+
+    public void testConsumeMatch()
+    {
+        CharSequence seq = "xx <!-- yy --> zz";
+        CallbackListener listener = new ParseCallbackListener();
+        ReducedHTMLParser parser = new ReducedHTMLParser(seq, listener);
+
+        // test non-match
+        assertFalse("Match non-matching pattern", parser.consumeMatch("ffff"));
+
+        // test valid match. Also verifies that previous match failure didn't
+        // move the parsing offset.
+        assertTrue("Match matching pattern", parser.consumeMatch("xx"));
+
+        // this won't match until whitespace removed
+        assertFalse("Match non-matching pattern", parser.consumeMatch("<!--"));
+        parser.consumeWhitespace();
+        assertTrue("Match matching pattern", parser.consumeMatch("<!--"));
+
+        // repeat
+        assertFalse("Match non-matching pattern", parser.consumeMatch("yy"));
+        parser.consumeWhitespace();
+        assertTrue("Match matching pattern", parser.consumeMatch("yy"));
+
+        parser.consumeWhitespace();
+        assertTrue("Match matching pattern", parser.consumeMatch("-->"));
+
+        // match at end of sequence
+        parser.consumeWhitespace();
+        assertTrue("Match matching pattern", parser.consumeMatch("zz"));
+
+        // check no exception on matching on finished sequence
+        assertFalse("Match non-matching pattern", parser.consumeMatch("aa"));
+    }
+
+    public void testConsumeElementName()
+    {
+        CharSequence seq = "  foo  t:foo t:FooBar t:foo_bar element-name/>";
+        CallbackListener listener = new ParseCallbackListener();
+        ReducedHTMLParser parser = new ReducedHTMLParser(seq, listener);
+
+        // test that consumeElementName will automatically skip any leading whitespace
+        String name1 = parser.consumeElementName();
+        assertEquals("Element name matched", "foo", name1);
+
+        String name2 = parser.consumeElementName();
+        assertEquals("Element name matched", "t:foo", name2);
+
+        String name3 = parser.consumeElementName();
+        assertEquals("Element name matched", "t:FooBar", name3);
+
+        String name4 = parser.consumeElementName();
+        assertEquals("Element name matched", "t:foo_bar", name4);
+
+        String name5 = parser.consumeElementName();
+        assertEquals("Element name matched", "element-name", name5);
+    }
+
+    public void testConsumeStringBasic()
+    {
+        CharSequence s1 = "'string1' \"string2\"";
+        CallbackListener listener = new ParseCallbackListener();
+        ReducedHTMLParser parser = new ReducedHTMLParser(s1, listener);
+
+        // Note that the consumeString method always expects the leading quote to
+        // have been consumed already..
+
+        // test single-quote delimited
+        parser.consumeMatch("'");
+        String str1 = parser.consumeString('\'');
+        assertEquals("String correctly parsed", "string1", str1);
+
+        // test double-quote delimited
+        parser.consumeWhitespace();
+        parser.consumeMatch("\"");
+        String str2 = parser.consumeString('\"');
+        assertEquals("String correctly parsed", "string2", str2);
+    }
+
+    public void testConsumeStringEscapedQuote()
+    {
+        char quoteMark = '\'';
+
+        // build literal sequence 'don\'t quote me' not-in-the-string
+        StringBuffer buf = new StringBuffer();
+        buf.append(quoteMark);
+        buf.append("don\\'t quote me");
+        buf.append(quoteMark);
+        buf.append(" not-in-the-string");
+
+        CallbackListener listener = new ParseCallbackListener();
+        ReducedHTMLParser parser = new ReducedHTMLParser(buf, listener);
+
+        // Note that the consumeString method always expects the leading quote to
+        // have been consumed already..
+
+        parser.consumeMatch("'");
+        String str1 = parser.consumeString('\'');
+        assertEquals("String correctly parsed", "don't quote me", str1);
+    }
+
+    public void testConsumeStringEscapedNonQuote()
+    {
+        char quoteMark = '"';
+
+        // build literal sequence 'don\'t quote me' not-in-the-string
+        StringBuffer buf = new StringBuffer();
+        buf.append(quoteMark);
+        buf.append("don\\'t quote me");
+        buf.append(quoteMark);
+        buf.append(" not-in-the-string");
+
+        CallbackListener listener = new ParseCallbackListener();
+        ReducedHTMLParser parser = new ReducedHTMLParser(buf, listener);
+
+        // Note that the consumeString method always expects the leading quote to
+        // have been consumed already..
+
+        parser.consumeMatch("\"");
+        String str1 = parser.consumeString('"');
+        assertEquals("String correctly parsed", "don\\'t quote me", str1);
+    }
+    
+    public void testConsumeStringEscapedEscape()
+    {
+        char quoteMark = '\'';
+        char backSlash = '\\';
+
+        // build literal sequence 'don\\'t escape me' not-in-the-string
+        // The double-backslash should be treated as a single backslash
+        // which does *not* escape the following quote.
+        StringBuffer buf = new StringBuffer();
+        buf.append(quoteMark);
+        buf.append("don");
+        buf.append(backSlash);
+        buf.append(backSlash);
+        buf.append(quoteMark);
+        buf.append("t escape me");
+        buf.append(quoteMark);
+
+        CallbackListener listener = new ParseCallbackListener();
+        ReducedHTMLParser parser = new ReducedHTMLParser(buf, listener);
+
+        // Note that the consumeString method always expects the leading quote to
+        // have been consumed already..
+
+        parser.consumeMatch("'");
+        String str1 = parser.consumeString('\'');
+        assertEquals("String correctly parsed", "don" + backSlash, str1);
+    }
+
+    public void testConsumeAttrValue()
+    {
+        CharSequence seq = "  bare 'quoted 1' \"quoted 2\" bare2 ";
+        CallbackListener listener = new ParseCallbackListener();
+        ReducedHTMLParser parser = new ReducedHTMLParser(seq, listener);
+
+        String val1 = parser.consumeAttrValue();
+        assertEquals("Attr value matched", "bare", val1);
+
+        String val2 = parser.consumeAttrValue();
+        assertEquals("Attr value matched", "quoted 1", val2);
+
+        String val3 = parser.consumeAttrValue();
+        assertEquals("Attr value matched", "quoted 2", val3);
+
+        String val4 = parser.consumeAttrValue();
+        assertEquals("Attr value matched", "bare2", val4);
+    }
+
+    public void testConsumeExcept()
+    {
+        CharSequence seq = "abc$$#dd  ee#ff-gghh ii";
+        CallbackListener listener = new ParseCallbackListener();
+        ReducedHTMLParser parser = new ReducedHTMLParser(seq, listener);
+
+        parser.consumeExcept("#e");
+        String val1 = parser.consumeNonWhitespace();
+        assertEquals("ConsumeExcept skipped expected chars", "#dd", val1);
+
+        parser.consumeExcept("z-");
+        String val2 = parser.consumeNonWhitespace();
+        assertEquals("ConsumeExcept skipped expected chars", "-gghh", val2);
+
+        // check that consumeExcept will reach end of buffer ok if none of
+        // the desired chars are found
+        assertFalse(parser.isFinished());
+        parser.consumeExcept("z");
+        assertTrue(parser.isFinished());
+
+        // check that calling consumeExcept is safe at end-of-buffer
+        parser.consumeExcept("z");
+    }
+
+    // test parsing completes when a lessthan is not followed by an element name,
+    // and there is just whitespace up to end of the input.
+    public void testParseBadTagNoElementName1()
+    {
+        String s = "xxxx \n\n <# \n\n";
+        CallbackListener listener = new ParseCallbackListener();
+        ReducedHTMLParser parser = new ReducedHTMLParser(s, listener);
+
+        parser.parse();
+        assertTrue(parser.isFinished());
+    }
+
+    // test parsing completes when a lessthan is not followed by an element name,
+    public void testParseBadTagNoElementName2()
+    {
+        String s = "xxxx \n\n <# \n\n hi there";
+        CallbackListener listener = new ParseCallbackListener();
+        ReducedHTMLParser parser = new ReducedHTMLParser(s, listener);
+
+        parser.parse();
+        assertTrue(parser.isFinished());
+    }
+
+    // test parsing completes when an invalid char is found where an attribute name
+    // is expected.
+    public void testParseBadTagInvalidAttributeName()
+    {
+        String s = "<foo )/>";
+        CallbackListener listener = new ParseCallbackListener();
+        ReducedHTMLParser parser = new ReducedHTMLParser(s, listener);
+
+        parser.parse();
+        assertTrue(parser.isFinished());
+    }
+
+    // test CDATA sections are handled
+    public void testParseCDATA()
+    {
+        String s = "xx<head> <![CDATA[ <head> ]]> <body>";
+        ParseCallbackListener listener = new ParseCallbackListener();
+        ReducedHTMLParser parser = new ReducedHTMLParser(s, listener);
+
+        parser.parse();
+        assertTrue(parser.isFinished());
+        assertEquals("CDATA works", 8, listener.afterHeadStart);
+        assertEquals("CDATA works", 30, listener.beforeBodyStart);
+    }
+
+    // test PI sections are handled
+    public void testParsePI()
+    {
+        String s = "<?xml version=\"1.0\"?> xx<head> ";
+        ParseCallbackListener listener = new ParseCallbackListener();
+        ReducedHTMLParser parser = new ReducedHTMLParser(s, listener);
+
+        parser.parse();
+        assertTrue(parser.isFinished());
+        assertEquals("PI works", 30, listener.afterHeadStart);
+    }
+
+    // Test script element support; the spec states that a <script> or
+    // <style> tag can contain anything except "/>"
+    public void testScript()
+    {
+        String s1 = "<head>";
+        String s2 = "<script type='text/javascript'>"
+                    + "if (1<2) alert('foo');\n"
+                    + "if (1>2) alert('bar');\n"
+                    + "</script>";
+        String s3 = "</head>";
+        String s4 = "<body>";
+        String s5 = "</body>";
+
+        StringBuffer buf = new StringBuffer();
+        buf.append(s1);
+        buf.append(s2);
+        buf.append(s3);
+        buf.append(s4);
+        buf.append(s5);
+
+        ParseCallbackListener listener = new ParseCallbackListener();
+        ReducedHTMLParser parser = new ReducedHTMLParser(buf.toString(), listener);
+
+        parser.parse();
+        assertTrue(parser.isFinished());
+        assertEquals("Script works", s1.length(), listener.afterHeadStart);
+        int beforeHeadEnd = s1.length() + s2.length();
+        assertEquals("Script works", beforeHeadEnd, listener.beforeHeadEnd);
+        int beforeBodyStart = beforeHeadEnd + s3.length();
+        assertEquals("Script works", beforeBodyStart, listener.beforeBodyStart);
+        int beforeBodyEnd = beforeBodyStart + s4.length();
+        assertEquals("Script works", beforeBodyEnd, listener.beforeBodyEnd);
+    }
+
+    // test the full parse method
+    public void testParse()
+    {
+        String s0 = "<!DOCTYPE PUBLIC \"sss\" \"http:foo\">\n";
+        String s1 = "<html><head>";
+        String s2 = "\n<!-- a comment --><title>foo</title>";
+        String s3 = "</head>";
+        String s4 = "< body onclick='zz'>";
+        String s5 = "  bodytext ";
+        // if comments aren't correctly parsed, then this will cause the
+        // head/body start positions to get corrupted.
+        String s6 = "  <!-- <head> <body> -->";
+        // if xml attr strings aren't correctly parsed, then this will cause
+        // the head/body start positions to get corrupted
+        String s7 = "<t:foo a1='<head>' a2='<body>'/>";
+        String s8 = "</body> </html>";
+
+        StringBuffer buf = new StringBuffer();
+        buf.append(s0);
+        buf.append(s1);
+        buf.append(s2);
+        buf.append(s3);
+        buf.append(s4);
+        buf.append(s5);
+        buf.append(s6);
+        buf.append(s7);
+        buf.append(s8);
+
+        ParseCallbackListener listener = new ParseCallbackListener();
+        ReducedHTMLParser parser = new ReducedHTMLParser(buf, listener);
+
+        parser.parse();
+
+        // check that listener has correctly computed the offset to the char just
+        // before the </head> tag starts.
+        int afterHeadStart = s0.length() + s1.length();
+        assertEquals("Pos after <head> tag ", afterHeadStart, listener.afterHeadStart);
+
+        int beforeBodyStart = afterHeadStart + s2.length() + s3.length();
+        assertEquals("Pos before <body> tag", beforeBodyStart, listener.beforeBodyStart);
+
+        int afterBodyStart = beforeBodyStart + s4.length();
+        assertEquals("Pos after <body> tag", afterBodyStart, listener.afterBodyStart);
+    }
+}

Added: myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/AbstractClassElementTestCase.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/AbstractClassElementTestCase.java?rev=963899&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/AbstractClassElementTestCase.java (added)
+++ myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/AbstractClassElementTestCase.java Tue Jul 13 22:57:38 2010
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.shared_tomahawk.test.ClassElementHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
+/**
+ * This test makes sure all of our components, tags, renderers, 
+ * validators, converters, action listeners, phase listeners and
+ * core implementation classes are in the build.
+ * 
+ * This class has been copy and pasted into both tomahawk and core 
+ * in order to avoid a compile scoped dependency on junit in shared.
+ * 
+ * @see ClassElementHandler
+ * @author Dennis Byrne
+ */
+
+public abstract class AbstractClassElementTestCase extends TestCase
+{
+
+    private Log log = LogFactory.getLog(AbstractClassElementTestCase.class);
+    
+    protected List resource = new ArrayList();
+    private List className = new ArrayList();
+        
+    public class DelegateEntityResolver extends ClassElementHandler
+    {
+        public DelegateEntityResolver()
+        {
+            super();
+        }
+
+        public InputSource resolveEntity(String publicId, String systemId)
+                throws SAXException, IOException
+        {
+            if (publicId.equals("-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"))
+            {
+                return new InputSource(Thread.currentThread()
+                        .getContextClassLoader().getResourceAsStream(
+                                "META-INF/dtd/web-jsptaglibrary_1_2.dtd"));
+            }
+            else if (publicId.equals("-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"))
+            {
+                return new InputSource(Thread.currentThread()
+                        .getContextClassLoader().getResourceAsStream(
+                                "org/apache/myfaces/resource/web-facesconfig_1_1.dtd"));                
+            }
+            else
+            {
+                return super.resolveEntity(publicId, systemId);
+            }
+        }
+    }    
+    
+    protected void setUp() throws Exception
+    {
+        SAXParserFactory factory = SAXParserFactory.newInstance();
+        factory.setValidating(false);
+        factory.setNamespaceAware(false);
+
+        SAXParser parser = factory.newSAXParser();
+        ClassElementHandler handler = new DelegateEntityResolver();
+        
+        Iterator iterator = resource.iterator();
+        
+        while(iterator.hasNext()){
+            
+            String resourceName = (String) iterator.next();
+            
+            InputStream is = getClass().getClassLoader()
+                .getResourceAsStream(resourceName);
+        
+            if(is == null)
+                is = Thread.currentThread().getContextClassLoader().getResourceAsStream(resourceName);
+        
+            if(is == null)
+                throw new Exception("Could not locate resource :" + resourceName);
+        
+            parser.parse(is, handler);
+            
+        }
+        
+        className.addAll(handler.getClassName());
+        
+    }
+    
+    public void testClassPath(){
+        
+        int i = 0;
+        for(  ; i < className.size() ; i++){
+            
+            String clazz = (String) className.get(i);
+            
+            try
+            {
+                getClass().getClassLoader().loadClass(clazz);
+                
+            }
+            catch (ClassNotFoundException e)
+            {
+                
+                try{
+                    
+                    Thread.currentThread().getContextClassLoader().loadClass(clazz);
+                    
+                }catch(ClassNotFoundException e2){
+                    
+                    assertFalse("Could not load " + clazz, true); 
+                    
+                }
+                
+            }
+            
+        }
+        
+        log.debug(( i + 1 ) + " class found ");
+        
+    }
+    
+}

Added: myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/AbstractTagLibTestCase.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/AbstractTagLibTestCase.java?rev=963899&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/AbstractTagLibTestCase.java (added)
+++ myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/AbstractTagLibTestCase.java Tue Jul 13 22:57:38 2010
@@ -0,0 +1,275 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import junit.framework.TestCase;
+import net.sf.maventaglib.checker.Tag;
+import net.sf.maventaglib.checker.TagAttribute;
+import net.sf.maventaglib.checker.Tld;
+import net.sf.maventaglib.checker.TldParser;
+
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.w3c.dom.Document;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * Insures the following ...
+ * <ul>
+ * <li> Tag handlers have setters for all tag attributes</li>
+ * <li> All tag handlers are in the classpath</li>
+ * <li> Tag handlers do not appear in the TLD more than once</li>
+ * <li> Tag handler attributes do not occur mare than once</li>
+ * </ul>
+ * 
+ * @author Dennis Byrne
+ * @see http://maven-taglib.sourceforge.net/ for dependency download
+ */
+
+public abstract class AbstractTagLibTestCase extends TestCase {
+    private static Log log = LogFactory.getLog(AbstractTagLibTestCase.class);
+
+    protected Tld[] tlds;
+
+    protected String[] tldPaths;
+    
+    private ClassLoader classLoader = getClass().getClassLoader();
+
+    /**
+     * Unmarshall TLDs to an object model. TLDs are supplied by a subclass.
+     */
+
+    protected void setUp() throws Exception {
+
+        if (tldPaths == null)
+            throw new NullPointerException(
+                    "tldPaths cannot point to null before setUp() is called");
+
+        int length = tldPaths.length;
+
+        if (length == 0)
+            throw new IllegalStateException(
+                    "tldPaths should have at least one resource path");
+
+        tlds = new Tld[length];
+
+        for (int t = 0; t < length; t++) {
+            String name = tldPaths[t];
+
+            InputStream stream = classLoader.getResourceAsStream(name);
+
+            if (stream == null)
+                throw new NullPointerException(
+                        "couldn't get an input stream for " + name);
+
+            tlds[t] = TldTestUtils.getTld(name, stream);
+            stream.close();
+        }
+    }
+
+    public void testUniqueTagTestCase() throws Exception {
+
+        for (int lib = 0; lib < tlds.length; lib++) {
+            Tld tld = tlds[lib];
+            List tagNames = new ArrayList();
+            Tag[] tags = tld.getTags();
+
+            for (int t = 0; t < tags.length; t++) {
+                Tag tag = tags[t];
+
+                if (tag == null)
+                    throw new NullPointerException("tag");
+
+                String name = tag.getName();
+                String msg = name + " found more than once in " + tldPaths[lib];
+                assertFalse(msg, tagNames.contains(name));
+                tagNames.add(name);
+            } // end t
+        } // end lib
+    }
+
+    public void testUniqueTagAttributes() throws Exception {
+
+        for (int lib = 0; lib < tlds.length; lib++) {
+            Tld tld = tlds[lib];
+            Tag[] tags = tld.getTags();
+
+            for (int t = 0; t < tags.length; t++) {
+
+                Tag tag = tags[t];
+                assertUniqueTagAttributes(tag, tldPaths[lib]);
+
+            } // end t
+        } // end lib
+    }
+
+    private void assertUniqueTagAttributes(final Tag tag, final String path) {
+
+        List attributeNames = new ArrayList();
+        TagAttribute[] atts = tag.getAttributes();
+        String tagName = tag.getName();
+
+        for (int a = 0; a < atts.length;) {
+
+            TagAttribute att = atts[a++];
+            String name = att.getAttributeName();
+            String msg = " @" + name + " of " + path + ":" + tagName
+                    + " is duplicated.";
+            assertFalse(msg, attributeNames.contains(name));
+            attributeNames.add(name);
+
+        } // end a
+
+    }
+
+    /**
+     * Make sure the class exists. Make sure there is a setter for each
+     * attribute.
+     */
+
+    public void testSetters() throws Exception {
+
+        for (int t = 0; t < tlds.length; t++) {
+            Tld tld = tlds[t];
+            Tag[] tags = tld.getTags();
+
+            for (int s = 0; s < tags.length; s++) {
+                Tag tag = tags[s];
+                String filename = tld.getFilename();
+
+                Object object = TldTestUtils.makeTagClassInstance(tag,
+                        filename, classLoader);
+                log.debug("filename = " + filename + " ; tag = " + tag.getName());
+                assertSetters(tag, filename, object);
+
+            } // end for tag
+        } // end for lib
+
+    }
+
+    private void assertSetters(final Tag tag, final String path,
+            final Object object) {
+
+        TagAttribute[] attributes = tag.getAttributes();
+        String tagName = tag.getName();
+
+        for (int a = 0; a < attributes.length; a++) {
+            TagAttribute attribute = attributes[a];
+            String name = attribute.getAttributeName();
+
+            if (name == null || "".equals(name.trim()))
+                throw new IllegalStateException(path + ":" + tagName
+                        + " has a nameless attribute ");
+
+            String msg = path + ":" + tagName + "@" + name
+                    + " exists, but " + object.getClass().getName()
+                    + " has no setter.";
+            
+            assertTrue(msg, PropertyUtils.isWriteable(object, name));
+        } // end for attributes
+
+    }
+    
+    private static class DelegateEntityResolver implements EntityResolver
+    {
+        private EntityResolver _delegate;
+
+        public DelegateEntityResolver(EntityResolver delegate)
+        {
+            this._delegate = delegate;
+        }
+
+        public InputSource resolveEntity(String publicId, String systemId)
+                throws SAXException, IOException
+        {
+            if (publicId.equals("-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"))
+            {
+                return new InputSource(Thread.currentThread()
+                        .getContextClassLoader().getResourceAsStream(
+                                "META-INF/dtd/web-jsptaglibrary_1_2.dtd"));
+            }
+            else
+            {
+                return _delegate.resolveEntity(publicId, systemId);
+            }
+        }
+    }    
+
+    private static class TldTestUtils {
+        private static Log log = LogFactory.getLog(TldTestUtils.class);
+
+        private static DocumentBuilderFactory dbf = DocumentBuilderFactory
+                .newInstance();
+        static
+        {
+            dbf.setNamespaceAware(false);
+            dbf.setValidating(false);
+        }
+
+        public static Tld getTld(String name, InputStream stream)
+                throws Exception {
+            if (stream == null)
+                log.error(" input stream is null ");
+
+            DocumentBuilder db = dbf.newDocumentBuilder();
+            db.setEntityResolver(new DelegateEntityResolver(null));
+            Document doc = db.parse(stream);
+
+            return TldParser.parse(doc, name);
+        }
+
+        public static Object makeTagClassInstance(Tag tag, String filename,
+                ClassLoader classLoader) throws Exception {
+
+            String clazzName = tag.getTagClass();
+
+            if (clazzName == null || "".equals(clazzName.trim()))
+                throw new NullPointerException(tag.getName()
+                        + " is missing a tag class.");
+
+            try {
+
+                Class clazz = classLoader.loadClass(clazzName);
+                return clazz.newInstance();
+
+            } catch (ClassNotFoundException e) {
+                throw new ClassNotFoundException(clazzName);
+            } catch (IllegalAccessException ie) {
+                throw new IllegalAccessException(clazzName);
+            } catch (InstantiationException iste) {
+                throw new InstantiationException(clazzName);
+            }
+
+        }
+
+    }
+
+}
\ No newline at end of file

Added: myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/AbstractTomahawkViewControllerTestCase.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/AbstractTomahawkViewControllerTestCase.java?rev=963899&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/AbstractTomahawkViewControllerTestCase.java (added)
+++ myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/AbstractTomahawkViewControllerTestCase.java Tue Jul 13 22:57:38 2010
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.test;
+
+import java.io.File;
+import java.io.StringWriter;
+
+import org.apache.myfaces.shared_tomahawk.config.MyfacesConfig;
+import org.apache.myfaces.test.base.AbstractViewControllerTestCase;
+import org.apache.myfaces.test.mock.MockResponseWriter;
+import org.apache.myfaces.test.mock.resource.MockResourceHandler;
+import org.apache.myfaces.test.utils.TestUtils;
+
+/**
+ * Abstract Shale Test base class, which sets up the JSF environment.  If the test
+ * overrides <code>setUp()</code> and/or <code>tearDown()</code>, then those
+ * methods but call the overwitten method to insure a valid test environment.
+ */
+public class AbstractTomahawkViewControllerTestCase extends AbstractViewControllerTestCase
+{
+    /** Response Writer */
+    private MockResponseWriter writer;
+    
+    //private MockResourceHandler resourceHandler;
+
+    /**
+     * Construct a new instance of the test.
+     * 
+     * @param name Name of the test.
+     */
+    public AbstractTomahawkViewControllerTestCase(String name)
+    {
+        super(name);
+    }
+
+    /**
+     *  Setup the test environment, including the following:
+     *  <ul>
+     *  <li>Set the Application Map.</li>
+     *  <li>Set a response writer</li>
+     *  <li>Add Tomahawk's renderers to the faces context.</li>
+     *  </ul> 
+     */
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+        // additional setup not provided automatically by the shale mock stuff
+        facesContext.getExternalContext().getApplicationMap().put(
+                MyfacesConfig.class.getName(), new MyfacesConfig());
+        writer = new MockResponseWriter(new StringWriter(), null, null);
+        facesContext.setResponseWriter(writer);
+        
+        //resourceHandler = new MockResourceHandler(new File(this.getClass().getName().replace('.', '/')));
+        //facesContext.getApplication().setResourceHandler(resourceHandler);
+        
+        TestUtils.addDefaultRenderers(facesContext);
+    }
+
+    /**
+     * Tear down the test environment.
+     */
+    protected void tearDown() throws Exception
+    {
+        //resourceHandler = null;
+        writer = null;
+        super.tearDown();
+    }
+
+    /**
+     * Verify the following:
+     * <ul>
+     * <li>id is not null</li>
+     * <li>Response is complete</li>
+     * <li>Responce contains the id</li>
+     * </ul>
+     * 
+     * @param id ID to verify
+     */
+    protected void assertIdExists(String id)
+    {
+        assertNotNull("ID is not null", id);
+        assertTrue("Response Complete", facesContext.getResponseComplete());
+        String output = writer.getWriter().toString();
+//        System.out.println("Output = '" + output + "'");
+        assertNotNull("Has output", output);
+        assertTrue("Contains id '" + id + "'", output.indexOf(id) != -1);
+    }
+
+}

Added: myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/MyFacesTagLibTestCase.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/MyFacesTagLibTestCase.java?rev=963899&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/MyFacesTagLibTestCase.java (added)
+++ myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/MyFacesTagLibTestCase.java Tue Jul 13 22:57:38 2010
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.test;
+
+/**
+ * @author Dennis C. Byrne
+ */
+
+public class MyFacesTagLibTestCase extends AbstractTagLibTestCase {
+
+    protected static final String META_INF = "META-INF/";
+
+    public MyFacesTagLibTestCase(){
+
+        // TODO get the sandbox in here
+
+        tldPaths = new String[3];
+        tldPaths[0] = META_INF + "myfaces_html.tld";
+        tldPaths[1] = META_INF + "myfaces_core.tld";
+        tldPaths[2] = META_INF + "tomahawk.tld";
+        // tldPaths[3] = META_INF + "myfaces_sandbox.tld";
+
+    }
+
+}

Added: myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/TomahawkClassElementTestCase.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/TomahawkClassElementTestCase.java?rev=963899&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/TomahawkClassElementTestCase.java (added)
+++ myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/TomahawkClassElementTestCase.java Tue Jul 13 22:57:38 2010
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+package org.apache.myfaces.test;
+
+/**
+ * @author Dennis Byrne
+ */
+
+public class TomahawkClassElementTestCase extends AbstractClassElementTestCase
+{
+
+    public TomahawkClassElementTestCase(){
+        
+        resource.add("META-INF/tomahawk.tld");
+        resource.add("META-INF/faces-config.xml");
+        
+    }
+    
+}

Added: myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/utils/HtmlCheckAttributesUtil.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/utils/HtmlCheckAttributesUtil.java?rev=963899&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/utils/HtmlCheckAttributesUtil.java (added)
+++ myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/utils/HtmlCheckAttributesUtil.java Tue Jul 13 22:57:38 2010
@@ -0,0 +1,246 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.test.utils;
+
+import java.util.Map;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+
+import org.apache.myfaces.test.mock.MockResponseWriter;
+
+/**
+ * This is a utility class used in unit test cases to check if
+ * a component's attributes are rendered properly.
+ */
+public class HtmlCheckAttributesUtil 
+{
+    /**
+     * This method adds all elements of attrs to the attributes map of component.
+     * @param component The component to add the attributes to.
+     * @param attrs     The attributes to be added to the component.
+     */
+    private static void addBaseAttributes(UIComponent component, HtmlRenderedAttr[] attrs) 
+    {
+        Map map = component.getAttributes();
+        for(int i = 0; i < attrs.length; i++) 
+        {
+            HtmlRenderedAttr attr = attrs[i];
+            map.put(attr.getName(), attr.getValue());
+        }
+    }
+    
+    /**
+     * Iterates through all elements of attrs to check if they are only rendered once in output.
+     * @param attrs      The attributes to be checked.
+     * @param output     The html output of the component's renderer.
+     * @throws Exception
+     */
+    private static void checkRenderedAttributes(HtmlRenderedAttr[] attrs, String output) throws Exception 
+    {
+        for(int i = 0; i < attrs.length; i++) 
+        {
+            //assertContainsOnlyOnce(attrs[i], output);
+            checkAttributeOccurrences(attrs[i], output);
+        }
+    }
+    
+    /**
+     * This method adds all attributes from attrs into the component.  After adding the attributes,
+     * it calls the encodeAll() method of the component.  The html generated from the component's
+     * renderer will be checked to see if the attributes have been rendered correctly.
+     * @param component  The component whose attributes will be tested.
+     * @param context    
+     * @param writer     The ResponseWriter used by the renderer to output the html generated.
+     * @param attrs      An array of attributes which will be tested.
+     * @throws Exception
+     */
+    public static void checkRenderedAttributes(
+            UIComponent component, 
+            FacesContext context, 
+            MockResponseWriter writer,
+            HtmlRenderedAttr[] attrs) throws Exception 
+    {
+        
+        addBaseAttributes(component, attrs);
+        component.encodeBegin(context);
+        component.encodeChildren(context);
+        component.encodeEnd(context);
+        context.renderResponse();
+        checkRenderedAttributes(attrs, writer.getWriter().toString());
+    }
+    
+    /**
+     * Checks the attrs array if it has elements which were rendered incorrectly.
+     * @param attrs The attributes to be checked.
+     * @return True if there are attributes not rendered correctly.
+     */
+    public static boolean hasFailedAttrRender(HtmlRenderedAttr[] attrs) 
+    {
+        for(int i = 0; i < attrs.length; i++) 
+        {
+            if(!attrs[i].isRenderSuccessful()) return true;
+        }
+        return false;
+    }
+    
+    /**
+     * Constructs an error message string detailing which attributes were not rendered
+     * and which attributes were rendered more than once.
+     * @param attrs   The attributes to be tested.
+     * @param actual  The html generated by the renderer.
+     * @return The error message.
+     */
+    public static String constructErrorMessage(HtmlRenderedAttr[] attrs, String actual) 
+    {
+        StringBuffer messgBuffer = new StringBuffer();
+        for(int i = 0; i < attrs.length; i++) 
+        {
+            if(attrs[i].getErrorCode() == HtmlRenderedAttr.RENDERED_MORE_TIMES_THAN_EXPECTED) 
+            {
+                messgBuffer.append(attrs[i].getName()).append(" (");
+                messgBuffer.append(attrs[i].getExpectedHtml()).append(") was rendered more times (");
+                messgBuffer.append(attrs[i].getActualOccurrences()).append(") than expected (");
+                messgBuffer.append(attrs[i].getExpectedOccurrences()).append(").");
+                messgBuffer.append(System.getProperty("line.separator"));
+            } 
+            else if(attrs[i].getErrorCode() == HtmlRenderedAttr.RENDERED_LESS_TIMES_THAN_EXPECTED)
+            {
+                messgBuffer.append(attrs[i].getName()).append(" (");
+                messgBuffer.append(attrs[i].getExpectedHtml()).append(") was rendered less times (");
+                messgBuffer.append(attrs[i].getActualOccurrences()).append(") than expected (");
+                messgBuffer.append(attrs[i].getExpectedOccurrences()).append(").");
+                messgBuffer.append(System.getProperty("line.separator"));
+            }
+        }
+        messgBuffer.append("Actual HTML: ").append(actual);
+        return messgBuffer.toString();
+    }
+    
+    /**
+     * Checks if the occurrence of the rendered attribute in the html
+     * generated by the renderer is equal to the number of times expected.
+     * @param attr   The attribute to be tested.
+     * @param actual The html generated by the renderer.
+     */
+    private static void checkAttributeOccurrences(HtmlRenderedAttr attr, String actual)
+    {
+        String expectedHtml = attr.getExpectedHtml();
+        
+        int index;
+        int offset = 0;
+        while((index=actual.indexOf(expectedHtml,offset)) != -1) 
+        {
+            attr.increaseActualOccurrences();
+            if(attr.getActualOccurrences() > attr.getExpectedOccurrences()) 
+            {
+                attr.setErrorCode(HtmlRenderedAttr.RENDERED_MORE_TIMES_THAN_EXPECTED);
+                return;
+            } 
+
+            offset += index + expectedHtml.length();
+        }
+        
+        if(attr.getActualOccurrences() < attr.getExpectedOccurrences()) 
+        {
+            attr.setErrorCode(HtmlRenderedAttr.RENDERED_LESS_TIMES_THAN_EXPECTED);
+        } 
+        else 
+        {
+            attr.setRenderSuccessful(true);
+        }
+    }
+    
+    public static HtmlRenderedAttr[] generateBasicAttrs() {
+        HtmlRenderedAttr[] attrs = {
+            //_AccesskeyProperty
+            new HtmlRenderedAttr("accesskey"),
+            //_UniversalProperties
+            new HtmlRenderedAttr("dir"), 
+            new HtmlRenderedAttr("lang"), 
+            new HtmlRenderedAttr("title"),
+            //_FocusBlurProperties
+            new HtmlRenderedAttr("onfocus"), 
+            new HtmlRenderedAttr("onblur"),
+            //_ChangeSelectProperties
+            new HtmlRenderedAttr("onchange"), 
+            new HtmlRenderedAttr("onselect"),
+            //_EventProperties
+            new HtmlRenderedAttr("onclick"), 
+            new HtmlRenderedAttr("ondblclick"), 
+            new HtmlRenderedAttr("onkeydown"), 
+            new HtmlRenderedAttr("onkeypress"),
+            new HtmlRenderedAttr("onkeyup"), 
+            new HtmlRenderedAttr("onmousedown"), 
+            new HtmlRenderedAttr("onmousemove"), 
+            new HtmlRenderedAttr("onmouseout"),
+            new HtmlRenderedAttr("onmouseover"), 
+            new HtmlRenderedAttr("onmouseup"),
+            //_StyleProperties
+            new HtmlRenderedAttr("style"), 
+            new HtmlRenderedAttr("styleClass", "styleClass", "class=\"styleClass\""),
+            //_TabindexProperty
+            new HtmlRenderedAttr("tabindex")
+        };
+        
+        return attrs;
+    }
+    
+    public static HtmlRenderedAttr[] generateAttrsNotRenderedForReadOnly() 
+    {
+        HtmlRenderedAttr[] attrs = {
+            //_AccesskeyProperty
+            new HtmlRenderedAttr("accesskey", 0),
+            //_FocusBlurProperties
+            new HtmlRenderedAttr("onfocus", 0), 
+            new HtmlRenderedAttr("onblur", 0),
+            //_ChangeSelectProperties
+            new HtmlRenderedAttr("onchange", 0), 
+            new HtmlRenderedAttr("onselect", 0),
+            //_TabindexProperty
+            new HtmlRenderedAttr("tabindex", 0)
+        };
+        return attrs;
+    }
+    
+    public static HtmlRenderedAttr[] generateBasicReadOnlyAttrs() {
+        HtmlRenderedAttr[] attrs = {
+            //_UniversalProperties
+            new HtmlRenderedAttr("dir"), 
+            new HtmlRenderedAttr("lang"), 
+            new HtmlRenderedAttr("title"),
+            //_EventProperties
+            new HtmlRenderedAttr("onclick"), 
+            new HtmlRenderedAttr("ondblclick"), 
+            new HtmlRenderedAttr("onkeydown"), 
+            new HtmlRenderedAttr("onkeypress"),
+            new HtmlRenderedAttr("onkeyup"), 
+            new HtmlRenderedAttr("onmousedown"), 
+            new HtmlRenderedAttr("onmousemove"), 
+            new HtmlRenderedAttr("onmouseout"),
+            new HtmlRenderedAttr("onmouseover"), 
+            new HtmlRenderedAttr("onmouseup"),
+            //_StyleProperties
+            new HtmlRenderedAttr("style"), 
+            new HtmlRenderedAttr("styleClass", "styleClass", "class=\"styleClass\""),
+        };
+        
+        return attrs;
+    }
+}

Added: myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/utils/HtmlRenderedAttr.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/utils/HtmlRenderedAttr.java?rev=963899&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/utils/HtmlRenderedAttr.java (added)
+++ myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/utils/HtmlRenderedAttr.java Tue Jul 13 22:57:38 2010
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.test.utils;
+
+public class HtmlRenderedAttr
+{
+    public static final int RENDERED_MORE_TIMES_THAN_EXPECTED = 1;
+    public static final int RENDERED_LESS_TIMES_THAN_EXPECTED = 2;
+    
+    private String name;
+    private String value;
+    private String expectedHtml;
+    private boolean renderSuccessful;
+    private int errorCode;
+    private int expectedOccurrences;
+    private int actualOccurrences;
+    
+    public HtmlRenderedAttr(String name) {
+        this(name, name, name + "=\"" + name + "\"");
+        expectedOccurrences = 1;
+    }
+    
+    public HtmlRenderedAttr(String name, int expectedOccurences) {
+        this(name);
+        this.expectedOccurrences = expectedOccurences;
+    }
+    
+    /**
+     * Represents an attribute of a component that is expected to be
+     * rendered into html
+     * @param name  The name of the attribute.
+     * @param value The value of the attribute.
+     * @param expectedHtml The expected html output for this attribute.  
+     *     E.g. name="value".
+     */
+    public HtmlRenderedAttr(String name, String value, String expectedHtml) {
+        this.name = name;
+        this.value = value;
+        this.expectedHtml = expectedHtml;
+        
+        renderSuccessful = false;
+        expectedOccurrences = 1;
+    }
+    
+    public HtmlRenderedAttr(String name, String value, String expectedHtml, int occurances) {
+        this(name, value, expectedHtml);
+        this.expectedOccurrences = occurances;
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    public String getValue()
+    {
+        return value;
+    }
+
+    public void setValue(String value)
+    {
+        this.value = value;
+    }
+
+    public String getExpectedHtml()
+    {
+        return expectedHtml;
+    }
+
+    public void setExpectedHtml(String expectedHtml)
+    {
+        this.expectedHtml = expectedHtml;
+    }
+
+    /**
+     * This returns the result of the rendering of the attribute.
+     * @return True if the rendered html output of this attribute is
+     * the same as expectedHtml.  False if either the attribute was not
+     * rendered, it was rendered multiple times, or the rendered html
+     * is different from expectedHtml.
+     */
+    public boolean isRenderSuccessful()
+    {
+        return renderSuccessful;
+    }
+
+    public void setRenderSuccessful(boolean renderSuccessful)
+    {
+        this.renderSuccessful = renderSuccessful;
+    }
+
+    public int getErrorCode()
+    {
+        return errorCode;
+    }
+
+    public void setErrorCode(int errorCode)
+    {
+        this.errorCode = errorCode;
+        setRenderSuccessful(false);
+    }
+    
+    public void increaseActualOccurrences() {
+        actualOccurrences++;
+    }
+    
+    public int getActualOccurrences() {
+        return this.actualOccurrences;
+    }
+    
+    public int getExpectedOccurrences() {
+        return this.expectedOccurrences;
+    }
+}

Added: myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/utils/MockTestViewHandler.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/utils/MockTestViewHandler.java?rev=963899&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/utils/MockTestViewHandler.java (added)
+++ myfaces/tomahawk/trunk/core20/src/test/java/org/apache/myfaces/test/utils/MockTestViewHandler.java Tue Jul 13 22:57:38 2010
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.test.utils;
+
+import javax.faces.context.FacesContext;
+
+import org.apache.myfaces.test.mock.MockViewHandler;
+
+/**
+ * This class is a temporary workaround for test cases
+ * that need a MockViewHandler that doesn't throw an
+ * UnsupportedOperationException inside writeState().
+ * This is not needed anymore once the fix for
+ * SHALE-468 is released.
+ */
+public class MockTestViewHandler extends MockViewHandler
+{
+    public void writeState(FacesContext context)
+    {
+        //do nothing
+    }
+}