| /********************************************************************* |
| * Copyright (c) 2004, 2007 Boeing |
| * |
| * This program and the accompanying materials are made |
| * available under the terms of the Eclipse Public License 2.0 |
| * which is available at https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Boeing - initial API and implementation |
| **********************************************************************/ |
| |
| package org.eclipse.osee.ote.core; |
| |
| import java.lang.ref.WeakReference; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Set; |
| import java.util.logging.Level; |
| |
| import javax.xml.stream.XMLStreamException; |
| import javax.xml.stream.XMLStreamWriter; |
| |
| import org.eclipse.osee.framework.jdk.core.persistence.Xmlizable; |
| import org.eclipse.osee.framework.jdk.core.persistence.XmlizableStream; |
| import org.eclipse.osee.framework.jdk.core.type.OseeCoreException; |
| import org.eclipse.osee.framework.jdk.core.util.xml.Jaxp; |
| import org.eclipse.osee.framework.jdk.core.util.xml.XMLStreamWriterUtil; |
| import org.eclipse.osee.framework.logging.OseeLog; |
| import org.eclipse.osee.ote.core.enums.PromptResponseType; |
| import org.eclipse.osee.ote.core.environment.EnvironmentTask; |
| import org.eclipse.osee.ote.core.environment.TestEnvironment; |
| import org.eclipse.osee.ote.core.environment.interfaces.ICancelTimer; |
| import org.eclipse.osee.ote.core.environment.interfaces.IExecutionUnitManagement; |
| import org.eclipse.osee.ote.core.environment.interfaces.IScriptControl; |
| import org.eclipse.osee.ote.core.environment.interfaces.ITestEnvironmentAccessor; |
| import org.eclipse.osee.ote.core.environment.interfaces.ITestLogger; |
| import org.eclipse.osee.ote.core.environment.interfaces.ITestStation; |
| import org.eclipse.osee.ote.core.environment.interfaces.ITimeout; |
| import org.eclipse.osee.ote.core.environment.interfaces.ITimerControl; |
| import org.eclipse.osee.ote.core.log.record.RequirementRecord; |
| import org.eclipse.osee.ote.core.log.record.TestCaseRecord; |
| import org.eclipse.osee.ote.core.log.record.TestDescriptionRecord; |
| import org.eclipse.osee.ote.core.log.record.TestRecord; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| |
| import com.fasterxml.jackson.annotation.JsonProperty; |
| |
| /** |
| * TestCase is the abstract base class for all test cases. This class provides the interfaces necessary for a TestCase |
| * to be part of a {@link org.eclipse.osee.ote.core.TestScript TestScript}. |
| * <p> |
| * The TestCase class contains the following information: |
| * <ul> |
| * <li><b>Standalone</b> - This is used to determine if a TestCase can be used in a selective run list. |
| * <ul> |
| * <li><b>true</b> - The TestCase runs as expected regardless of order. |
| * <li><b>false</b> - The TestCase must be run in a given order with other test cases to work as expected. |
| * </ul> |
| * <li><b>Test Case Number</b> - A serial number automatically assigned at the time of construction. |
| * <li><b>Tracability</b> - The requirements that are tested by this TestCase. |
| * </ul> |
| * <p> |
| * When building a new TestCase object it is important to remember that the object contains information describing the |
| * test case in addition to the run time code. It is also important to understand that the when writing classes which |
| * within a TestScript that the object must be instantiated (typically done in the constructor) with a reference to the |
| * TestScript it is within or else it will not be executed. |
| * <p> |
| * The following sample should be followed closely when building TestCase objects. <br> |
| * <br> |
| * <code> |
| * public class OipCase extends TestCase { |
| * <ul style="list-style: none"> |
| * <li> public OipCase(TestScript parent) { |
| * <ul style="list-style: none"> |
| * <li> </code><i>Use <b>one</b> of the following constructors based on if this TestCase is standalone</i><code> |
| * <li> super(parent);</code> <i>Standalone defaulted to <b>false</b></i><code> |
| * <li> super(parent, true);</code><i>Standalone explicitly set to <b>true</b></i><code> |
| * <li> |
| * <li> </code><i>All requirements tested in the test case should be noted here with the </i> |
| * <code>{@link org.eclipse.osee.ote.core.TestCase#addTracability(String) addTracability}</code><i> method.</i> <code> |
| * </ul> |
| * <li> } |
| * <li> |
| * <li> </code><i><b>Note:</b>It is very important that </i><code>doTestCase</code><i> always has the </i> |
| * <code>throws InterrupedException</code><i> in the method declaration. The ability to abort a script relies on this |
| * statement, and without it many calls would have to be wrapped with a try/catch block.</i><code> |
| * <li> public void doTestCase(ITestEnvironmentAccessor environment, ITestLogger logger) throws InterruptedException { |
| * <ul style="list-style: none"> |
| * <li> </code><i>Place all of the runtime code for the test case here.</i><code> |
| * </ul> |
| * <li> } |
| * </ul> |
| * } |
| * </code> |
| * |
| * @see org.eclipse.osee.ote.core.TestScript |
| * @author Ryan D. Brooks |
| * @author Robert A. Fisher |
| */ |
| public abstract class TestCase implements ITestEnvironmentAccessor, Xmlizable, XmlizableStream { |
| protected ITestLogger logger; |
| private final ITestEnvironmentAccessor environment; |
| private final boolean standAlone; |
| private final WeakReference<TestScript> testScript; |
| private final TestDescriptionRecord testDescription; |
| @JsonProperty |
| public int number; |
| protected List<RequirementRecord> traceability = new ArrayList<>(); |
| |
| public TestCase(TestScript testScript) { |
| this(testScript, false); |
| } |
| |
| public TestCase(TestScript testScript, boolean standAlone) { |
| this(testScript, standAlone, true); |
| } |
| |
| protected TestCase(TestScript testScript, boolean standAlone, boolean addToRunList) { |
| super(); |
| this.testDescription = new TestDescriptionRecord(testScript.getTestEnvironment()); |
| this.standAlone = standAlone; |
| if (addToRunList) { |
| this.number = testScript.addTestCase(this); |
| } |
| this.testScript = new WeakReference<>(testScript); |
| this.environment = testScript.getTestEnvironment(); |
| GCHelper.getGCHelper().addRefWatch(this); |
| } |
| |
| /** |
| * Called by baseDoTestCase(). This is implemented by the tester's in each test case in the test |
| * script. |
| * |
| * @param environment The Test environment. |
| * @param logger |
| * @throws InterruptedException |
| */ |
| public abstract void doTestCase(ITestEnvironmentAccessor environment, ITestLogger logger) throws InterruptedException; |
| |
| public Element getTastCaseNumberXml(Document doc) { |
| return Jaxp.createElement(doc, "Number", String.valueOf(number)); |
| } |
| |
| public void writeTestCaseNumber(XMLStreamWriter writer) throws XMLStreamException { |
| XMLStreamWriterUtil.writeElement(writer, "Number", String.valueOf(number)); |
| } |
| |
| public void writeTestCaseClassName(XMLStreamWriter writer) throws XMLStreamException { |
| String name = this.getClass().getName(); |
| if (name == null || name.length() == 0) { |
| name = ""; |
| } |
| XMLStreamWriterUtil.writeElement(writer, "Name", name); |
| } |
| |
| @JsonProperty |
| public String getName() { |
| return this.getClass().getName(); |
| } |
| |
| public void writeTracability(XMLStreamWriter writer) throws XMLStreamException { |
| writer.writeStartElement("Tracability"); |
| for (RequirementRecord record : traceability) { |
| record.toXml(writer); |
| } |
| writer.writeEndElement(); |
| } |
| |
| public Element getTestCaseClassName(Document doc) { |
| String name = this.getClass().getName(); |
| if (name == null || name.length() == 0) { |
| name = ""; |
| } |
| return Jaxp.createElement(doc, "Name", name); |
| } |
| |
| public String getTestCaseClassName() { |
| return this.getClass().getName(); |
| } |
| |
| public TestCase getTestCase() { |
| return this; |
| } |
| |
| /** |
| * @return Returns the testCaseNumber. |
| */ |
| public int getTestCaseNumber() { |
| return number; |
| } |
| |
| public ITestEnvironmentAccessor getTestEnvironment() { |
| return environment; |
| } |
| |
| public TestRecord getTestRecord() { |
| return new TestCaseRecord(getTestEnvironment(), this); |
| } |
| |
| /** |
| * @return Returns the testScript. |
| */ |
| @Override |
| public TestScript getTestScript() { |
| return testScript.get(); |
| } |
| |
| public Element getTracabilityXml(Document doc) { |
| Element traceElement = doc.createElement("Tracability"); |
| for (RequirementRecord record : traceability) { |
| traceElement.appendChild(record.toXml(doc)); |
| |
| } |
| return traceElement; |
| } |
| |
| /** |
| * @return Returns the standAlone. |
| */ |
| public boolean isStandAlone() { |
| return standAlone; |
| } |
| |
| public void prompt() { |
| getTestScript().prompt(); |
| } |
| |
| public void prompt(String message) { |
| getTestScript().prompt(new TestPrompt(message, PromptResponseType.NONE)); |
| } |
| |
| public void promptPassFail(String message) { |
| getTestScript().getLogger().methodCalled(getTestScript().getTestEnvironment(), |
| new MethodFormatter().add(message)); |
| |
| getTestScript().promptPassFail(message); |
| |
| getTestScript().getLogger().methodEnded(getTestScript().getTestEnvironment()); |
| } |
| |
| public void promptPause(String message) { |
| getTestScript().promptPause(message); |
| } |
| |
| public void promptStep(String message) { |
| getTestScript().prompt(new TestPrompt(message, PromptResponseType.SCRIPT_STEP)); |
| } |
| |
| public String promptInput(String message) { |
| return getTestScript().prompt(new TestPrompt(message, PromptResponseType.USER_INPUT)); |
| } |
| |
| /** |
| * Logs the results of a test point. |
| * |
| * @param passed boolean T/F |
| * @param expected The expected information |
| * @param actual The actual information |
| */ |
| public void testpoint(boolean passed, String testPointName, String expected, String actual) { |
| logger.testpoint(this.getTestEnvironment(), this.getTestScript(), this, passed, testPointName, expected, actual); |
| } |
| |
| @Override |
| public String toString() { |
| String description = getTestScript().getClass().getName() + "Test Case " + number + ":"; |
| if (traceability != null) { |
| for (RequirementRecord record : traceability) { |
| description += "\n\t" + record; |
| } |
| } |
| return description; |
| } |
| |
| @Override |
| public Element toXml(Document doc) { |
| Element testCaseElement = doc.createElement("TestCase"); |
| testCaseElement.appendChild(getTastCaseNumberXml(doc)); |
| testCaseElement.appendChild(getTestCaseClassName(doc)); |
| testCaseElement.appendChild(getTracabilityXml(doc)); |
| return testCaseElement; |
| } |
| |
| @Override |
| public void toXml(XMLStreamWriter writer) throws XMLStreamException { |
| writer.writeStartElement("TestCase"); |
| writeTestCaseNumber(writer); |
| writeTestCaseClassName(writer); |
| writeTracability(writer); |
| } |
| |
| /** |
| * Starts running the test case. Calls doTestCase(), which is implemented by the tester in each test case. |
| * |
| * @param environment The Test Enviornment. |
| */ |
| public void baseDoTestCase(ITestEnvironmentAccessor environment) { |
| this.logger = environment.getLogger(); |
| |
| logger.testCaseBegan(this); // This is required for valid outfile. |
| //This creates the test case outfile logging. |
| |
| environment.getTestScript().setTestCase(this); |
| OseeLog.logf(TestEnvironment.class, OteLevel.TEST_EVENT, "Starting Test Case %s.%s", |
| this.getTestScript().getClass().getSimpleName(), this.getClass().getSimpleName()); |
| try { |
| doTestCase(environment, environment.getLogger()); |
| } catch (InterruptedException e) { |
| OseeCoreException.wrapAndThrow(e); |
| } |
| } |
| |
| @Override |
| public void abortTestScript() { |
| environment.abortTestScript(); |
| } |
| |
| @Override |
| public boolean addTask(EnvironmentTask task) { |
| return environment.addTask(task); |
| } |
| |
| @Override |
| public void associateObject(Class<?> c, Object obj) { |
| environment.associateObject(c, obj); |
| } |
| |
| @Override |
| public Object getAssociatedObject(Class<?> c) { |
| return environment.getAssociatedObject(c); |
| } |
| |
| @Override |
| public Set<Class<?>> getAssociatedObjects() { |
| return environment.getAssociatedObjects(); |
| } |
| |
| /* |
| * public ITestEnvironmentCommandCallback getClientCallback() { return environment.getClientCallback(); } |
| */ |
| |
| // public EnvironmentType getEnvironmentType() { |
| // return environment.getEnvironmentType(); |
| // } |
| @Override |
| public long getEnvTime() { |
| return environment.getEnvTime(); |
| } |
| |
| @Override |
| public IExecutionUnitManagement getExecutionUnitManagement() { |
| return environment.getExecutionUnitManagement(); |
| } |
| |
| @Override |
| public ITestLogger getLogger() { |
| return environment.getLogger(); |
| } |
| |
| @Override |
| public IScriptControl getScriptCtrl() { |
| return environment.getScriptCtrl(); |
| } |
| |
| /* |
| * public StatusBoard getStatusBoard() { return environment.getStatusBoard(); } |
| */ |
| |
| @Override |
| public ITestStation getTestStation() { |
| return environment.getTestStation(); |
| } |
| |
| @Override |
| public ITimerControl getTimerCtrl() { |
| return environment.getTimerCtrl(); |
| } |
| |
| @Override |
| public void onScriptComplete() throws InterruptedException { |
| environment.onScriptComplete(); |
| } |
| |
| @Override |
| public void onScriptSetup() { |
| environment.onScriptSetup(); |
| } |
| |
| @Override |
| public ICancelTimer setTimerFor(ITimeout listener, int time) { |
| return environment.setTimerFor(listener, time); |
| } |
| |
| public void logTestPoint(boolean isPassed, String testPointName, String expected, String actual) { |
| this.getLogger().testpoint(this.getTestEnvironment(), this.getTestScript(), this, isPassed, testPointName, |
| expected, actual); |
| } |
| |
| public void setPurpose(String purpose) { |
| testDescription.setPurpose(purpose); |
| } |
| |
| public void setPreCondition(String preCondition) { |
| testDescription.setPreCondition(preCondition); |
| } |
| |
| public void setPostCondition(String postCondition) { |
| testDescription.setPostCondition(postCondition); |
| } |
| |
| public List<RequirementRecord> getScriptReqRecordTraceability() { |
| return traceability; |
| } |
| |
| public void addTraceability(String description) { |
| this.traceability.add(new RequirementRecord(this.getTestEnvironment(), description)); |
| } |
| |
| public void writeToConsole(String message) { |
| TestPrompt p = new TestPrompt(message); |
| |
| try { |
| testScript.get().prompt(p); |
| } catch (Throwable e) { |
| OseeLog.log(TestEnvironment.class, Level.INFO, e.getMessage(), e); |
| } |
| } |
| |
| public void setTestScript(TestScript script) { |
| throw new IllegalStateException("Why are you calling this one?!?!?!?"); |
| } |
| |
| @JsonProperty |
| public List<RequirementRecord> getTraceability() { |
| if (traceability.isEmpty()) { |
| return null; |
| } else { |
| return traceability; |
| } |
| } |
| } |