From 6f290d8f9e9d7faac295cb51fc96884a18f4ded4 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Thu, 21 May 2009 04:36:41 +0000 Subject: Initial KLEE checkin. - Lots more tweaks, documentation, and web page content is needed, but this should compile & work on OS X & Linux. git-svn-id: https://llvm.org/svn/llvm-project/klee/trunk@72205 91177308-0d34-0410-b5e6-96231b3b80d8 --- unittests/Solver/Makefile | 11 +++ unittests/Solver/SolverTest.cpp | 164 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 unittests/Solver/Makefile create mode 100644 unittests/Solver/SolverTest.cpp (limited to 'unittests/Solver') diff --git a/unittests/Solver/Makefile b/unittests/Solver/Makefile new file mode 100644 index 00000000..583025fb --- /dev/null +++ b/unittests/Solver/Makefile @@ -0,0 +1,11 @@ +##===- unittests/Solver/Makefile ---------------------------*- Makefile -*-===## + +LEVEL := ../.. +TESTNAME := Solver +USEDLIBS := kleaverSolver.a kleaverExpr.a kleeSupport.a kleeBasic.a +LINK_COMPONENTS := support + +include $(LEVEL)/Makefile.config +include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest + +LIBS += -lstp diff --git a/unittests/Solver/SolverTest.cpp b/unittests/Solver/SolverTest.cpp new file mode 100644 index 00000000..1b1e0f3f --- /dev/null +++ b/unittests/Solver/SolverTest.cpp @@ -0,0 +1,164 @@ +//===-- SolverTest.cpp ----------------------------------------------------===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" + +#include "klee/Constraints.h" +#include "klee/Expr.h" +#include "klee/Solver.h" + +using namespace klee; + +namespace { + +const int g_constants[] = { -1, 1, 4, 17, 0 }; +const Expr::Width g_types[] = { Expr::Bool, + Expr::Int8, + Expr::Int16, + Expr::Int32, + Expr::Int64 }; + +ref getConstant(int value, Expr::Width width) { + int64_t ext = value; + uint64_t trunc = ext & (((uint64_t) -1LL) >> (64 - width)); + return ConstantExpr::create(trunc, width); +} + + +template +void testOperation(Solver &solver, + int value, + Expr::Width operandWidth, + Expr::Width resultWidth) { + std::vector symbolicArgs; + + for (unsigned i = 0; i < T::numKids; i++) { + if (!T::isValidKidWidth(i, operandWidth)) + return; + + unsigned size = Expr::getMinBytesForWidth(operandWidth); + static unsigned id = 0; + Array *array = new Array(0, ++id, size); + symbolicArgs.push_back(Expr::CreateArg(Expr::createTempRead(array, + operandWidth))); + } + + if (T::needsResultType()) + symbolicArgs.push_back(Expr::CreateArg(resultWidth)); + + ref fullySymbolicExpr = Expr::createFromKind(T::kind, symbolicArgs); + + // For each kid, replace the kid with a constant value and verify + // that the fully symbolic expression is equivalent to it when the + // replaced value is appropriated constrained. + for (unsigned kid = 0; kid < T::numKids; kid++) { + std::vector partiallyConstantArgs(symbolicArgs); + for (unsigned i = 0; i < T::numKids; i++) + if (i==kid) + partiallyConstantArgs[i] = getConstant(value, operandWidth); + + ref expr = + NotOptimizedExpr::create(EqExpr::create(partiallyConstantArgs[kid].expr, + symbolicArgs[kid].expr)); + + ref partiallyConstantExpr = + Expr::createFromKind(T::kind, partiallyConstantArgs); + + ref queryExpr = EqExpr::create(fullySymbolicExpr, + partiallyConstantExpr); + + ConstraintManager constraints; + constraints.addConstraint(expr); + bool res; + bool success = solver.mustBeTrue(Query(constraints, queryExpr), res); + EXPECT_EQ(true, success) << "Constraint solving failed"; + + if (success) { + EXPECT_EQ(true, res) << "Evaluation failed!\n" + << "query " << queryExpr + << " with " << expr; + } + } +} + +template +void testOpcode(Solver &solver, bool tryBool = true, bool tryZero = true, + unsigned maxWidth = 64) { + for (unsigned j=0; j maxWidth) continue; + + for (unsigned i=0; i(solver, value, type, type); + continue; + } + + for (unsigned k=0; k= + Expr::getMinBytesForWidth(resultType)) + continue; + } + + testOperation(solver, value, type, resultType); + } + } + } +} + +TEST(SolverTest, Evaluation) { + STPSolver *stpSolver = new STPSolver(true); + Solver *solver = stpSolver; + + solver = createCexCachingSolver(solver); + solver = createCachingSolver(solver); + solver = createIndependentSolver(solver); + + testOpcode(*solver); + testOpcode(*solver); + testOpcode(*solver); + + testOpcode(*solver); + testOpcode(*solver); + testOpcode(*solver, false, true, 8); + testOpcode(*solver, false, false, 8); + testOpcode(*solver, false, false, 8); + testOpcode(*solver, false, false, 8); + testOpcode(*solver, false, false, 8); + testOpcode(*solver, false); + testOpcode(*solver, false); + testOpcode(*solver, false); + testOpcode(*solver); + testOpcode(*solver); + testOpcode(*solver); + + testOpcode(*solver); + testOpcode(*solver); + testOpcode(*solver); + testOpcode(*solver); + testOpcode(*solver); + testOpcode(*solver); + testOpcode(*solver); + testOpcode(*solver); + testOpcode(*solver); + testOpcode(*solver); + + delete solver; +} + +} -- cgit 1.4.1