aboutsummaryrefslogtreecommitdiffhomepage
path: root/unittests/Expr/ArrayExprTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'unittests/Expr/ArrayExprTest.cpp')
-rw-r--r--unittests/Expr/ArrayExprTest.cpp75
1 files changed, 75 insertions, 0 deletions
diff --git a/unittests/Expr/ArrayExprTest.cpp b/unittests/Expr/ArrayExprTest.cpp
new file mode 100644
index 00000000..47375abd
--- /dev/null
+++ b/unittests/Expr/ArrayExprTest.cpp
@@ -0,0 +1,75 @@
+//===-- ExprTest.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 <iostream>
+
+#include "../../lib/Expr/ArrayExprOptimizer.h"
+#include "klee/Expr/ArrayCache.h"
+#include "klee/Expr/Assignment.h"
+#include "klee/Expr/Expr.h"
+#include <llvm/Support/CommandLine.h>
+
+using namespace klee;
+namespace klee {
+extern llvm::cl::opt<ArrayOptimizationType> OptimizeArray;
+}
+
+namespace {
+
+ref<Expr> getConstant(int value, Expr::Width width) {
+ int64_t ext = value;
+ uint64_t trunc = ext & (((uint64_t)-1LL) >> (64 - width));
+ return ConstantExpr::create(trunc, width);
+}
+
+static ArrayCache ac;
+
+TEST(ArrayExprTest, HashCollisions) {
+ klee::OptimizeArray = ALL;
+ std::vector<ref<ConstantExpr>> constVals(256,
+ ConstantExpr::create(5, Expr::Int8));
+ const Array *array = ac.CreateArray("arr0", 256, constVals.data(),
+ constVals.data() + constVals.size(),
+ Expr::Int32, Expr::Int8);
+ const Array *symArray = ac.CreateArray("symIdx", 4);
+ ref<Expr> symIdx = Expr::createTempRead(symArray, Expr::Int32);
+ UpdateList ul(array, 0);
+ ul.extend(getConstant(3, Expr::Int32), getConstant(11, Expr::Int8));
+ ref<Expr> firstRead = ReadExpr::create(ul, symIdx);
+ ul.extend(getConstant(6, Expr::Int32), getConstant(42, Expr::Int8));
+ ul.extend(getConstant(6, Expr::Int32), getConstant(42, Expr::Int8));
+ ref<Expr> updatedRead = ReadExpr::create(ul, symIdx);
+
+ // This test requires hash collision and should be updated if the hash
+ // function changes
+ ASSERT_NE(updatedRead, firstRead);
+ ASSERT_EQ(updatedRead->hash(), firstRead->hash());
+
+ std::vector<unsigned char> value = {6, 0, 0, 0};
+ std::vector<std::vector<unsigned char>> values = {value};
+ std::vector<const Array *> assigmentArrays = {symArray};
+ auto a = std::make_unique<Assignment>(assigmentArrays, values,
+ /*_allowFreeValues=*/true);
+
+ EXPECT_NE(a->evaluate(updatedRead), a->evaluate(firstRead));
+ EXPECT_EQ(a->evaluate(updatedRead), getConstant(42, Expr::Int8));
+ EXPECT_EQ(a->evaluate(firstRead), getConstant(5, Expr::Int8));
+
+ ExprOptimizer opt;
+ auto oFirstRead = opt.optimizeExpr(firstRead, true);
+ auto oUpdatedRead = opt.optimizeExpr(updatedRead, true);
+ EXPECT_NE(oFirstRead, firstRead);
+ EXPECT_NE(updatedRead, oUpdatedRead);
+
+ EXPECT_NE(a->evaluate(oUpdatedRead), a->evaluate(oFirstRead));
+ EXPECT_EQ(a->evaluate(oUpdatedRead), getConstant(42, Expr::Int8));
+ EXPECT_EQ(a->evaluate(oFirstRead), getConstant(5, Expr::Int8));
+}
+}