/* * Copyright (C) 2014-2015 Daniel Dietsch (dietsch@informatik.uni-freiburg.de) * Copyright (C) 2014-2015 Matthias Heizmann (heizmann@informatik.uni-freiburg.de) * Copyright (C) 2015 University of Freiburg * * This file is part of the ULTIMATE UnitTest Library. * * The ULTIMATE UnitTest Library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The ULTIMATE UnitTest Library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the ULTIMATE UnitTest Library. If not, see . * * Additional permission under GNU GPL version 3 section 7: * If you modify the ULTIMATE UnitTest Library, or any covered work, by linking * or combining it with Eclipse RCP (or a modified version of Eclipse RCP), * containing parts covered by the terms of the Eclipse Public License, the * licensors of the ULTIMATE UnitTest Library grant you additional permission * to convey the resulting work. */ package de.uni_freiburg.informatik.ultimate.test.decider; import java.util.regex.Pattern; import de.uni_freiburg.informatik.ultimate.core.lib.results.ExceptionOrErrorResult; import de.uni_freiburg.informatik.ultimate.test.UltimateRunDefinition; import de.uni_freiburg.informatik.ultimate.test.decider.expectedresult.IExpectedResultFinder; import de.uni_freiburg.informatik.ultimate.test.decider.expectedresult.KeywordBasedExpectedResultFinder; import de.uni_freiburg.informatik.ultimate.test.decider.overallresult.IOverallResultEvaluator; import de.uni_freiburg.informatik.ultimate.test.decider.overallresult.SafetyCheckerOverallResult; import de.uni_freiburg.informatik.ultimate.test.decider.overallresult.SafetyCheckerOverallResultEvaluator; import de.uni_freiburg.informatik.ultimate.test.util.TestUtil; /** * Use keywords in filename and first line to decide correctness of safety checker results. * * @author heizmann@informatik.uni-freiburg.de * @author Daniel Dietsch (dietsch@informatik.uni-freiburg.de) * */ public class SafetyCheckTestResultDecider extends ThreeTierTestResultDecider { /** * * @param ultimateRunDefinition * @param unknownIsJUnitSuccess * if true the TestResult UNKNOWN is a success for JUnit, if false, the TestResult UNKNOWN is a failure * for JUnit. * * @param overridenExpectedVerdict * The expected verdict overridden in a separate file, null if not present. */ public SafetyCheckTestResultDecider(final UltimateRunDefinition ultimateRunDefinition, final boolean unknownIsJUnitSuccess, final String overridenExpectedVerdict) { super(ultimateRunDefinition, unknownIsJUnitSuccess, overridenExpectedVerdict); } /** * * @param ultimateRunDefinition * @param unknownIsJUnitSuccess * if true the TestResult UNKNOWN is a success for JUnit, if false, the TestResult UNKNOWN is a failure * for JUnit. */ public SafetyCheckTestResultDecider(final UltimateRunDefinition ultimateRunDefinition, final boolean unknownIsJUnitSuccess) { super(ultimateRunDefinition, unknownIsJUnitSuccess); } @Override public IExpectedResultFinder constructExpectedResultFinder() { return new KeywordBasedExpectedResultFinder<>(TestUtil.constructFilenameKeywordMap_AllSafetyChecker(), null, TestUtil.constructFirstlineKeywordMap_SafetyChecker()); } @Override public IOverallResultEvaluator constructUltimateResultEvaluation() { return new SafetyCheckerOverallResultEvaluator(); } @Override public ITestResultEvaluation constructTestResultEvaluation() { return new SafetyCheckerTestResultEvaluation(); } public class SafetyCheckerTestResultEvaluation implements ITestResultEvaluation { private String mCategory; private String mMessage; private TestResult mTestResult; @Override public void evaluateTestResult(final IExpectedResultFinder expectedResultFinder, final IOverallResultEvaluator overallResultDeterminer) { if (mOverridenExpectedVerdict != null) { final SafetyCheckerOverallResult overallResult = overallResultDeterminer.getOverallResult(); final String overallResultMsg = overallResultDeterminer.generateOverallResultMessage(); final Pattern pattern = Pattern.compile(mOverridenExpectedVerdict, Pattern.CASE_INSENSITIVE); if (pattern.matcher(overallResult.toString()) != null || pattern.matcher(overallResultMsg) != null) { mTestResult = TestResult.IGNORE; } else { mTestResult = TestResult.FAIL; } mCategory = overallResult + " (Expected to match :" + mOverridenExpectedVerdict + ")"; mMessage = " UltimateResult: " + overallResultMsg; return; } evaluateExpectedResult(expectedResultFinder); switch (expectedResultFinder.getExpectedResultFinderStatus()) { case ERROR: // we will not evaluate overall result; return; case EXPECTED_RESULT_FOUND: compareToOverallResult(expectedResultFinder.getExpectedResult(), overallResultDeterminer); return; case NO_EXPECTED_RESULT_FOUND: evaluateOverallResultWithoutExpectedResult(overallResultDeterminer); return; default: throw new IllegalArgumentException(); } } private void evaluateOverallResultWithoutExpectedResult( final IOverallResultEvaluator overallResultDeterminer) { final SafetyCheckerOverallResult overallResult = overallResultDeterminer.getOverallResult(); final String overallResultMsg = overallResultDeterminer.generateOverallResultMessage(); mCategory = overallResult + " (Expected:UNKNOWN)"; mMessage += " UltimateResult: " + overallResultMsg; switch (overallResult) { case EXCEPTION_OR_ERROR: case UNSUPPORTED_SYNTAX: case NO_RESULT: mTestResult = TestResult.FAIL; break; case SAFE: case UNSAFE: case UNSAFE_DEREF: case UNSAFE_FREE: case UNSAFE_MEMTRACK: case UNSAFE_OVERAPPROXIMATED: case UNKNOWN: case SYNTAX_ERROR: case TIMEOUT: mTestResult = TestResult.UNKNOWN; break; default: throw new AssertionError("case not implemented: " + overallResult); } } private void compareToOverallResult(final SafetyCheckerOverallResult expectedResult, final IOverallResultEvaluator overallResultDeterminer) { final SafetyCheckerOverallResult overallResult = overallResultDeterminer.getOverallResult(); final String overallResultMsg = overallResultDeterminer.generateOverallResultMessage(); mCategory = overallResult + " (Expected:" + expectedResult + ")"; mMessage += " UltimateResult: " + overallResult + " " + overallResultMsg; switch (overallResult) { case EXCEPTION_OR_ERROR: mCategory = overallResult + " (Expected:" + expectedResult + ") " + overallResultMsg; mTestResult = TestResult.FAIL; break; case SAFE: if (expectedResult == SafetyCheckerOverallResult.SAFE) { mTestResult = TestResult.SUCCESS; } else { mTestResult = TestResult.FAIL; } break; case UNSAFE: case UNSAFE_DEREF: case UNSAFE_FREE: case UNSAFE_MEMTRACK: if (expectedResult == overallResult) { mTestResult = TestResult.SUCCESS; } else if (expectedResult == SafetyCheckerOverallResult.UNSAFE) { mTestResult = TestResult.SUCCESS; } else { mTestResult = TestResult.FAIL; } break; case UNSAFE_OVERAPPROXIMATED: if (expectedResult == overallResult) { mTestResult = TestResult.SUCCESS; } else if (expectedResult == SafetyCheckerOverallResult.UNSAFE) { mTestResult = TestResult.SUCCESS; } else { mTestResult = TestResult.UNKNOWN; } break; case INVALID_ANNOTATION: case VALID_ANNOTATION: if (expectedResult == overallResult) { mTestResult = TestResult.SUCCESS; } else { mTestResult = TestResult.FAIL; } break; case UNKNOWN: // syntax error should always have been found if (expectedResult == SafetyCheckerOverallResult.SYNTAX_ERROR) { mTestResult = TestResult.FAIL; } else { mTestResult = TestResult.UNKNOWN; } break; case SYNTAX_ERROR: if (expectedResult == SafetyCheckerOverallResult.SYNTAX_ERROR) { mTestResult = TestResult.SUCCESS; } else { mTestResult = TestResult.FAIL; } break; case TIMEOUT: // syntax error should always have been found if (expectedResult == SafetyCheckerOverallResult.SYNTAX_ERROR) { mTestResult = TestResult.FAIL; } else { mTestResult = TestResult.UNKNOWN; } break; case UNSUPPORTED_SYNTAX: mTestResult = TestResult.FAIL; break; case NO_RESULT: mTestResult = TestResult.FAIL; break; default: throw new AssertionError("case not implemented: " + overallResult); } } private void evaluateExpectedResult( final IExpectedResultFinder expectedResultFinder) throws AssertionError { switch (expectedResultFinder.getExpectedResultFinderStatus()) { case ERROR: mCategory = "Inconsistent keywords"; mMessage = expectedResultFinder.getExpectedResultFinderMessage(); mTestResult = TestResult.FAIL; break; case EXPECTED_RESULT_FOUND: mMessage = "ExpectedResult: " + expectedResultFinder.getExpectedResult(); break; case NO_EXPECTED_RESULT_FOUND: mMessage = expectedResultFinder.getExpectedResultFinderMessage(); break; default: throw new AssertionError( "case not implemented: " + expectedResultFinder.getExpectedResultFinderStatus()); } } @Override public void evaluateTestResult(final IExpectedResultFinder expectedResultFinder, final Throwable e) { evaluateExpectedResult(expectedResultFinder); switch (expectedResultFinder.getExpectedResultFinderStatus()) { case ERROR: // we will not evaluate overall result; return; case EXPECTED_RESULT_FOUND: case NO_EXPECTED_RESULT_FOUND: mCategory += "UltimateResult: " + SafetyCheckerOverallResult.EXCEPTION_OR_ERROR + " " + e.getMessage(); final ExceptionOrErrorResult res = new ExceptionOrErrorResult("Unknown", e); mMessage += " UltimateResult: " + res.getLongDescription(); return; default: throw new AssertionError( "case not implemented: " + expectedResultFinder.getExpectedResultFinderStatus()); } } @Override public TestResult getTestResult() { return mTestResult; } @Override public String getTestResultCategory() { return mCategory; } @Override public String getTestResultMessage() { return mMessage; } } }