/*

   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.batik.test;

/**
 * This <code>Test</code> implementation can be used to validate the
 * operation of a specific test. A typical use is to create
 * known error conditions and check that the input <code>Test</code>
 * reports these errors properly.
 * <p>
 * This test checks that a given test status (passed or not)
 * and a given error code is returned by a <code>Test</code>.
 * A <code>TestReportValidator</code> is built with the <code>Test</code> to
 * run, the expected status (passed or failed) and the expected
 * error code. The <code>TestReportValidator</code> will pass if the
 * expected values are produced by the <code>TestReport</code>
 * created by the associated <code>Test</code>. Otherwise, it will
 * fail with one of two error codes:<br>
 * + if the status is not the one expected, then the
 *   ERROR_UNEXPECTED_TEST_STATUS code is used.. The report
 *   description will have two entries: ENTRY_KEY_EXPECTED_STATUS
 *   and ENTRY_KEY_RECEIVED_STATUS, both of which are Strings.
 * + if the status is the one expected, but if the error code
 *   differs from the expected one, then the
 *   ERROR_UNEXPECTED_ERROR_CODE code is used. The report
 *   description will have two entries: ENTRY_KEY_EXPECTED_ERROR_CODE
 *   and ENTRY_KEY_RECEIVED_ERROR_CODE.
 *
 * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
 * @version $Id: TestReportValidator.java 1805408 2017-08-18 12:21:52Z ssteiner $
 */
public class TestReportValidator extends AbstractTest {
    /**
     * Test that this validator checks
     */
    private Test test;

    /**
     * Status expected from the <code>TestReport</code>
     */
    private boolean expectedStatus;

    /**
     * Error code expected from the <code>TestReport</code>
     */
    private String expectedErrorCode;

    /**
     * Error code used when the test status is
     * is different from the expected status.
     */
    static final String ERROR_UNEXPECTED_TEST_STATUS
        = "TestReportValidator.error.unexpected.test.status";

    /**
     * Error code used when the test error code is
     * different from the expected error code.
     */
    static final String ERROR_UNEXPECTED_ERROR_CODE
        = "TestReportValidator.error.unexpected.error.code";

    /**
     * The error description entry when the test fails
     */
    public static final String ENTRY_KEY_EXPECTED_ERROR_CODE
        = "TestReportValidator.entry.key.expected.error.code";

    /**
     * Entry describing the received error code which is
     * different from the expected one.
     */
    public static final String ENTRY_KEY_RECEIVED_ERROR_CODE
        = "TestReportValidator.entry.key.received.error.code";

    /**
     * The entry describing the expected status when the test status
     * is unexpected.
     */
    public static final String ENTRY_KEY_EXPECTED_STATUS
        = "TestReportValidator.entry.key.expected.status";

    /**
     * Entry describing the received status which is
     * different from the expected one.
     */
    public static final String ENTRY_KEY_RECEIVED_STATUS
        = "TestReportValidator.entry.key.received.status";

    /**
     * Constructor
     *
     */
    public TestReportValidator(Test test,
                               boolean expectedStatus,
                               String expectedErrorCode){
        setConfig(test,
                  expectedStatus,
                  expectedErrorCode);
    }

    /**
     * Protected constructor, for use by derived classes
     */
    protected TestReportValidator(){
    }

    /**
     * Lets derived classes set the configuration parameters
     * for this test.
     */
    protected void setConfig(Test test,
                             boolean expectedStatus,
                             String expectedErrorCode){
        this.expectedErrorCode = expectedErrorCode;
        this.test = test;
        this.expectedStatus = expectedStatus;
    }

    public TestReport runImpl() throws Exception {
        TestReport tr = test.run();

        //
        // Check test output
        //
        DefaultTestReport r = new DefaultTestReport(this);

        if( tr.hasPassed() != expectedStatus ){
            TestReport.Entry expectedStatusEntry
                = new TestReport.Entry(Messages.formatMessage(ENTRY_KEY_EXPECTED_STATUS, null),
                                       (Boolean.valueOf(expectedStatus)).toString());
            TestReport.Entry receivedStatusEntry
                = new TestReport.Entry(Messages.formatMessage(ENTRY_KEY_RECEIVED_STATUS, null),
                                       (Boolean.valueOf(tr.hasPassed())).toString());
            r.setDescription(new TestReport.Entry[]{ expectedStatusEntry, receivedStatusEntry });
            r.setErrorCode(ERROR_UNEXPECTED_TEST_STATUS);
            r.setPassed(false);
        }
        else if( tr.getErrorCode() != expectedErrorCode ){
            TestReport.Entry expectedErrorCodeEntry
                = new TestReport.Entry(Messages.formatMessage(ENTRY_KEY_EXPECTED_ERROR_CODE, null),
                                       expectedErrorCode);
            TestReport.Entry receivedErrorCodeEntry
                = new TestReport.Entry(Messages.formatMessage(ENTRY_KEY_RECEIVED_ERROR_CODE, null),
                                       tr.getErrorCode());

            r.setDescription(new TestReport.Entry[]{ expectedErrorCodeEntry, receivedErrorCodeEntry });
            r.setErrorCode(ERROR_UNEXPECTED_ERROR_CODE);
            r.setPassed(false);
        }

        return r;
    }
}
