Java tutorial
/* * 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.trinidadinternal.renderkit; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.Logger; import java.util.logging.SimpleFormatter; import javax.faces.component.UIComponent; import javax.faces.component.UIViewRoot; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import org.apache.commons.lang.StringUtils; import org.apache.myfaces.trinidad.context.Agent; import org.apache.myfaces.trinidad.context.RequestContext; import org.apache.myfaces.trinidad.render.ExtendedRenderKitService; import org.apache.myfaces.trinidad.util.Service; import org.apache.myfaces.trinidadbuild.test.FacesTestCase; import org.apache.myfaces.trinidadinternal.io.XhtmlResponseWriter; import junit.framework.AssertionFailedError; import junit.framework.TestCase; import junit.framework.TestResult; import junit.framework.TestSuite; import org.xml.sax.SAXException; abstract public class RenderKitTestCase extends TestSuite { public RenderKitTestCase(String testName) throws IOException, SAXException { super(testName); try { _initGlobal(); } catch (Exception e) { e.printStackTrace(); } _initTests(); } protected void setUp() throws Exception { } protected void tearDown() throws Exception { } @Override public void run(TestResult result) { try { setUp(); super.run(result); tearDown(); } catch (Exception e) { result.addError(this, e); } } abstract public class BaseTest extends FacesTestCase { public BaseTest(String name, SuiteDefinition definition) { this(name, definition.getCategory(), definition.getSkin(), definition.getAgent(), definition.getAccessibilityMode(), definition.isRightToLeft()); } public BaseTest(String name, String categoryName, String skin, Agent agent, RequestContext.Accessibility accMode, boolean rightToLeft) { super(name + "-" + categoryName); _skin = skin; _agent = agent; _accMode = accMode; _rightToLeft = rightToLeft; } @Override public void run(TestResult result) { // Cache the TestResult so we can directly add failure without // aborting the run _result = result; CatchSevere catchSevere = new CatchSevere(); Logger apacheLogger = Logger.getLogger("org.apache"); apacheLogger.addHandler(catchSevere); try { RenderKitBootstrap.setFactories(_facesConfigInfo); super.run(result); } finally { apacheLogger.removeHandler(catchSevere); RenderKitBootstrap.clearFactories(); } } @Override protected void setUp() throws IOException { _facesContext = new MFacesContext(MApplication.sharedInstance(), true); _requestContext = new MRequestContext(); _requestContext.setSkinFamily(_skin); _requestContext.setAgent(_agent); _requestContext.setRightToLeft(_rightToLeft); _requestContext.setAccessibilityMode(_accMode); UIViewRoot root = RenderKitBootstrap.createUIViewRoot(_facesContext); root.setRenderKitId(getRenderKitId()); _facesContext.setViewRoot(root); ExtendedRenderKitService service = _getExtendedRenderKitService(_facesContext); if (service != null) service.encodeBegin(_facesContext); } @Override protected void tearDown() throws IOException { ExtendedRenderKitService service = _getExtendedRenderKitService(_facesContext); if (service != null) { service.encodeEnd(_facesContext); service.encodeFinally(_facesContext); } MFacesContext.clearContext(); _requestContext.release(); _facesContext = null; _requestContext = null; _result = null; } @Override abstract protected void runTest() throws Throwable; protected FacesContext getFacesContext() { return _facesContext; } protected TestResult getResult() { return _result; } protected Agent getAgent() { return _agent; } protected void renderRoot(UIViewRoot root) throws IOException { RenderUtils.encodeRecursive(_facesContext, root); } protected void initializeContext(Writer out) throws IOException { _facesContext.getExternalContext().getRequestMap().clear(); _facesContext.setResponseWriter(_createResponseWriter(out)); } private ResponseWriter _createResponseWriter(Writer out) throws IOException { return new TestResponseWriter(out, XhtmlResponseWriter.XHTML_CONTENT_TYPE, "UTF-8", this, _result); } // Severe errors should count as a test failure private class CatchSevere extends Handler { @Override public void publish(LogRecord record) { if (record.getLevel() == Level.SEVERE) { String message = (new SimpleFormatter()).format(record); _result.addError(BaseTest.this, new AssertionFailedError(message)); } } @Override public void flush() { } @Override public void close() { } } private TestResult _result; private MFacesContext _facesContext; private MRequestContext _requestContext; private String _skin; private Agent _agent; private RequestContext.Accessibility _accMode; private boolean _rightToLeft; } public class RendererTest extends BaseTest { public RendererTest(String name, SuiteDefinition definition, boolean lenient) throws IOException, SAXException { super(name, definition); _scriptName = name + ".xml"; File scriptFile = new File(_scriptDir, _scriptName); _script = TestScriptParser.getTestScript(scriptFile, _facesConfigInfo); _lenient = lenient; // We run golden-file checks on each subtest - though all differences // get counted only as a single diff. We also do a comparison // of each subtest against the base, and verify that startComponent() // is correctly called if (lenient) _testCaseCount = 1; else _testCaseCount = (_script.getTests().size() * 3) + 1; } @Override public int countTestCases() { // See TRINIDAD-48: reporting anything other than the number // of actual JUnit testcases makes JUnit confused return 1;//_testCaseCount; } @Override public void run(TestResult result) { if (!_script.isSupportedAgentType(getAgent().getType())) { /* System.out.println("SKIPPING UNSUPPORTED SCRIPT: " + _scriptName); System.out.println("AGENT IS " + getAgent()); System.out.println("AGENT TYPE IS " + getAgent().getType()); */ return; } super.run(result); } @Override protected void tearDown() throws IOException { super.tearDown(); _script = null; } @SuppressWarnings("unchecked") @Override protected void runTest() throws Throwable { UIViewRoot root = getFacesContext().getViewRoot(); initializeContext(new NullWriter()); UIComponent docRoot = populateDefaultComponentTree(root, _script); StringWriter first = new StringWriter(); docRoot.getChildren().add(new GatherContent(first, _createComponent(), getResult(), this, _lenient)); StringWriter base = new StringWriter(); docRoot.getChildren().add(new GatherContent(base, _createComponent(), getResult(), this, _lenient)); Iterator<TestScript.Test> tests = _script.getTests().iterator(); while (tests.hasNext()) { TestScript.Test test = tests.next(); UIComponent testComponent = _createComponent(); test.apply(getFacesContext(), testComponent); docRoot.getChildren() .add(new GatherContent(test.getOutput(), testComponent, getResult(), this, _lenient)); } renderRoot(root); File goldenFile = new File(_goldenDir, getName() + "-golden.xml"); String golden = null; if (goldenFile.exists()) { StringBuffer buffer = new StringBuffer((int) goldenFile.length()); BufferedReader in = new BufferedReader(new FileReader(goldenFile)); while (true) { String line = in.readLine(); if (line == null) break; buffer.append(line); buffer.append('\n'); } golden = buffer.toString(); in.close(); } boolean forceGolden = "true".equals(System.getProperty("org.apache.myfaces.trinidad.ForceGolden")); Writer out = new StringWriter(golden == null ? 1000 : golden.length()); out.write("<results>"); String baseResults = base.toString(); out.write(baseResults); tests = _script.getTests().iterator(); while (tests.hasNext()) { TestScript.Test test = tests.next(); out.write("\n<!--"); out.write(test.toString()); out.write("-->\n"); String testResults = test.getOutput().toString(); out.write(testResults); if (_lenient) continue; if (!test.shouldMatchBase() && baseResults.equals(testResults)) { AssertionFailedError failure = new AssertionFailedError("Result of " + test.toString() + " were identical to " + "base, but should not have been!"); getResult().addError(this, failure); } else if (test.shouldMatchBase() && !baseResults.equals(testResults)) { AssertionFailedError failure = new AssertionFailedError("Result of " + test.toString() + " were not identical to " + "base, but should have been!"); getResult().addError(this, failure); } } out.write("\n</results>\n"); out.close(); String results = out.toString(); if ((golden == null) || !golden.equals(results)) { File failureFile; // Set the "org.apache.myfaces.trinidad.ForceGolden" property to true to // force failures to be directly copied into the target directory if (forceGolden) failureFile = new File(_goldenDir, getName() + "-golden.xml"); else failureFile = new File(_failureDir, getName() + "-golden.xml"); failureFile.getParentFile().mkdirs(); FileWriter failureOut = new FileWriter(failureFile); failureOut.write(results); failureOut.close(); if (golden == null) { // Don't report "no golden file" as an error when // forceGolden is on; but do report diffs as errors if (!forceGolden) { throw new AssertionFailedError("No golden file for test " + _scriptName); } } else { int index = StringUtils.indexOfDifference(golden, results); String difference = StringUtils.difference(golden, results); int diffLength = difference.length(); if (diffLength > 50) difference = StringUtils.abbreviate(difference, 50); throw new AssertionFailedError( "Golden file for test " + _scriptName + " did not match; " + "first difference at " + index + ", difference of length " + diffLength + ", \"" + difference + "\""); } } } private UIComponent _createComponent() { return _script.getDefinition().createComponent(getFacesContext()); } private int _testCaseCount; private String _scriptName; private TestScript _script; private boolean _lenient; } static private void _initGlobal() throws IOException, SAXException { RenderKitBootstrap bootstrap = new RenderKitBootstrap(); bootstrap.init(); _facesConfigInfo = bootstrap.getFacesConfigInfo(); String scripts = System.getProperty("trinidad.renderkit.scripts"); String golden = System.getProperty("trinidad.renderkit.golden"); String failures = System.getProperty("trinidad.renderkit.failures"); _scriptDir = new File(scripts); _goldenDir = new File(golden); _failureDir = new File(failures); } private void _initTests() throws IOException, SAXException { String script = System.getProperty("trinidad.renderkit.script"); Set<String> includedScripts = null; if (script != null) { String[] scripts = script.split(","); includedScripts = new HashSet<String>(); for (int i = 0; i < scripts.length; i++) { System.out.println("Including " + scripts[i]); includedScripts.add(scripts[i]); } } // See if we want to run the full test suite (by default, no) String fulltests = System.getProperty("trinidad.renderkit.fulltests"); // We can run the full test suite in two modes: strict, and lenient. // We should go to "strict" all the time, but "lenient" simply // diffs against the golden files boolean lenient = "lenient".equals(fulltests); String[] scriptArray = _scriptDir.list(); for (int i = 0; i < scriptArray.length; i++) { String name = scriptArray[i]; if ((includedScripts != null) && !includedScripts.contains(name)) continue; if (name.endsWith(".xml")) { boolean first = true; name = name.substring(0, name.length() - 4); for (SuiteDefinition definition : getSuiteDefinitions()) { if (first) { addTest(new RendererTest(name, definition, false)); first = false; } else { addTest(new RendererTest(name, definition, lenient)); } } } } } protected abstract UIComponent populateDefaultComponentTree(UIViewRoot root, TestScript script); protected abstract Iterable<SuiteDefinition> getSuiteDefinitions(); protected abstract String getRenderKitId(); static public class SuiteDefinition { public SuiteDefinition(String category, String skin, RequestContext.Accessibility accessibilityMode, Agent agent, boolean rightToLeft) { _category = category; _skin = skin; _accessibilityMode = accessibilityMode; _agent = agent; _rightToLeft = rightToLeft; } public String getCategory() { return _category; } public String getSkin() { return _skin; } public RequestContext.Accessibility getAccessibilityMode() { return _accessibilityMode; } public Agent getAgent() { return _agent; } public boolean isRightToLeft() { return _rightToLeft; } private String _category; private String _skin; private RequestContext.Accessibility _accessibilityMode; private Agent _agent; private boolean _rightToLeft; } static private ExtendedRenderKitService _getExtendedRenderKitService(FacesContext context) { return Service.getService(context.getRenderKit(), ExtendedRenderKitService.class); } static private FacesConfigInfo _facesConfigInfo; static private File _scriptDir; static private File _goldenDir; static private File _failureDir; }